YungSherman
@YungSherman
Личинка программиста

Почему не работает запись в базу данных?

Я разрабатываю веб-приложение с помощью ASP.NET-Core и EntityFrameworkCore. Решил реализовать в нём чат с использованием WebSocket. За основу брал статью по этой ссылке. Работает вроде хорошо, хочу добавить запись сообщений в базу данных, но возникает проблема.

У меня есть такой класс модели сообщения:
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);
    }
}


Вот метод класса ChatWebSocketMiddleWare, в котором происходит получение и обработка сообщения:
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);
    }


Проблема в том, что запись сообщения в бд не происходит. В классах-контроллерах я использую тот же класс контекста и всё работает нормально. Я не могу понять, что я мог упустить.
  • Вопрос задан
  • 249 просмотров
Решения вопроса 1
YungSherman
@YungSherman Автор вопроса
Личинка программиста
Я решил сделать добавление в бд в другом методе класса ChatWebSocketMiddleWare, а именно Invoke(). В нем в параметрах передавался HttpContext, а также решил добавить параметр контекста доступа к бд. Всё стало работать нормально:
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();
        }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@FreeBa
А почему вы используете асинхронные методы в синхронном коде? Это несколько нелогично, и учитывая ленивую природу таких методов может привести к неоднозначному поведению - юзайте async/await.
Ответ написан
@basrach
вы упустили слово await перед context.SaveChangesAsync();
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы