实体框架添加性能随着更多行而降级

时间:2014-03-30 20:18:57

标签: c# asp.net performance linq entity-framework

我将从这篇文章开始,注意到我对.NET世界完全陌生。 ASP,EntityFramework,Linq等在这一点上都是未知的魔法。

话虽如此,我已经为自己构建了一个整洁的Web API聊天式应用程序,SignalR支持实时事件。它工作得很好,但我在添加功能方面遇到了一些性能问题。

在我的聊天应用程序中,有“Pads”(聊天室),其中包含许多“Mates”和“Messages”。这是我的Pad模型供参考:

public class Pad
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid PadId { get; set; }
    public string StreetAddress { get; set; }
    public int ZipCode { get; set; }
    public virtual ICollection<Mate> Mates { get; set; }
    public virtual ICollection<Message> Messages { get; set; }
}

我的问题在于我的SignalR集线器处理发送到特定打击垫的新消息。 这两行大约需要半秒钟来处理。

pad.Messages.Add(msg); // pad is the Pad entity already fetched from the db context
db.Messages.Add(msg);

但是当Pad.Messages包含大量消息时,它们只需要很长时间。数千人。 如果我发送的内容几乎没有消息,则会立即执行。

我在这里提高感知性能的最初'技巧'是将添加功能移动到之后我将通知发送回客户端,但我意识到这样的事情可能会在以后出现潜在问题当一个打击垫中有数十或数十万条消息时。

非常感谢任何建议!

以下是整个邮件发送方法供参考:

public void SendMessage(string pad_id, string body)
{
    var user_id = IdentityExtensions.GetUserId(Context.User.Identity);
    body = body.Trim();
    if (body.Length <= 0)
    {
        return;
    }
    // Check that the user belongs in this pad...
    var user = (from u in db.Users
                where u.Id == user_id
                select u).First();
    var pad = (from p in user.Pads where p.PadId == new Guid(pad_id) select p).FirstOrDefault();
    if (pad != null) {
        // Save the message to the database
        var msg = new Message()
        {
            MessageId = new Guid(),
            Author = user,
            Body = body,
            SendTime = DateTimeOffset.UtcNow,
            Pad = pad
        };

        pad.Messages.Add(msg); // These two lines
        db.Messages.Add(msg); // Are the culprit.
        db.SaveChangesAsync();
        Clients.Group(pad_id).messageReceived(user.Id, pad_id, body, DateTimeOffset.UtcNow); // Send message to clients
    }
}

编辑:我在使用EF 6.0.0

1 个答案:

答案 0 :(得分:0)

从您的代码中,您要做的就是在表格中添加1行(消息)。

在构造Message实体时,只需使用padid而不是Pad对象。 这样你就不需要处理所有的pad对象了。从数据库的角度来看,您只需要添加一个带有PadId键的Message行。

    var msg = new Message()
    {
        MessageId = new Guid(),
        Author = user,
        Body = body,
        SendTime = DateTimeOffset.UtcNow,
        PadId = new Guid(pad_id)
    };

    // pad.Messages.Add(msg); // don't need this.
    db.Messages.Add(msg);

以上内容应始终插入一行,而不是取决于打击垫中的消息数量。 如果它仍然存在性能问题,那么添加单行会导致对表进行大量索引更新。