Answer the question
In order to leave comments, you need to log in
Why is writing to the database not working?
I am developing a web application using ASP.NET-Core and EntityFrameworkCore. I decided to implement a chat in it using WebSocket. I took the article from this link as a basis. It seems to work well, I want to add a message record to the database, but there is a problem.
I have a message model class like this:
public class GroupChatMessage
{
public int ID { get; set; }
public int CompanyID { get; set; }
public int UserID { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime CreationDate { get; set; }
public string Text { get; set; }
public Company Company { get; set; }
[NotMapped]
public UserPlusWorkerModel UserPlusWorker { get; set; }
//public User User { get; set; }
}
public class EnterChatContext : DbContext
{
public EnterChatContext(DbContextOptions<EnterChatContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<TopicMessage> TopicMessages { get; set; }
public DbSet<Topic> Topics { get; set; }
public DbSet<Note> Notes { get; set; }
public DbSet<GroupChatMessage> GroupChatMessages { get; set; }
public DbSet<File> Files { get; set; }
public DbSet<Company> Companies { get; set; }
public DbSet<Worker> Workers { get; set; }
public DbSet<Department> Departments { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable("User");
modelBuilder.Entity<TopicMessage>().ToTable("TopicMessage");
modelBuilder.Entity<Topic>().ToTable("Topic");
modelBuilder.Entity<Note>().ToTable("Note");
modelBuilder.Entity<GroupChatMessage>().ToTable("GroupChatMessage");
modelBuilder.Entity<File>().ToTable("File");
modelBuilder.Entity<Company>().ToTable("Company");
modelBuilder.Entity<Worker>().ToTable("Worker");
modelBuilder.Entity<Department>().ToTable("Departments");
base.OnModelCreating(modelBuilder);
}
}
private static Task SendStringAsync(WebSocket socket, string data, CancellationToken ct = default(CancellationToken))
{
var buffer = Encoding.UTF8.GetBytes(data);
var segment = new ArraySegment<byte>(buffer);
var optionsBuilder = new DbContextOptionsBuilder<EnterChatContext>();
//optionsBuilder.UseSqlite("Server=(localdb)\\mssqllocaldb;Database=EnterChatWebDB;");
using (var context = new EnterChatContext(optionsBuilder.Options))
{
GroupChatMessage message = new GroupChatMessage
{
//просто тестовые данные
UserID = 1,
CompanyID = 1,
Text = data,
CreationDate = DateTime.Now
};
context.GroupChatMessages.AddAsync(message);
context.SaveChangesAsync();
}
return socket.SendAsync(segment, WebSocketMessageType.Text, true, ct);
}
Answer the question
In order to leave comments, you need to log in
I decided to add to the database in another method of the ChatWebSocketMiddleWare class, namely Invoke(). In it, HttpContext was passed in the parameters, and I also decided to add a parameter for the access context to the database. Everything started working fine:
public async Task Invoke(HttpContext context, EnterChatContext chatContext)
{
if (!context.WebSockets.IsWebSocketRequest)
{
await _next.Invoke(context);
return;
}
CancellationToken ct = context.RequestAborted;
WebSocket currentSocket = await context.WebSockets.AcceptWebSocketAsync();
var socketId = Guid.NewGuid().ToString();
_sockets.TryAdd(socketId, currentSocket);
while (true)
{
if (ct.IsCancellationRequested)
{
break;
}
var response = await ReceiveStringAsync(currentSocket, ct);
if (string.IsNullOrEmpty(response))
{
if (currentSocket.State != WebSocketState.Open)
{
break;
}
continue;
}
int user_id = Int32.Parse(context.User.FindFirst(ClaimTypes.NameIdentifier).Value);
int comp_id = Int32.Parse(context.User.FindFirst("CompanyID").Value);
GroupChatMessage message = new GroupChatMessage
{
UserID = user_id,
CompanyID = comp_id,
Text = response,
CreationDate = DateTime.Now
};
await chatContext.GroupChatMessages.AddAsync(message);
await chatContext.SaveChangesAsync();
foreach (var socket in _sockets)
{
if (socket.Value.State != WebSocketState.Open)
{
continue;
}
await SendStringAsync(socket.Value, response, ct);
}
}
WebSocket dummy;
_sockets.TryRemove(socketId, out dummy);
await currentSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct);
currentSocket.Dispose();
}
And why are you using asynchronous methods in synchronous code? This is somewhat counterintuitive, and given the lazy nature of such methods, can lead to ambiguous behavior - use async/await.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question