【问题标题】:Performance of Entity Framework [closed]实体框架的性能[关闭]
【发布时间】:2016-05-13 07:43:10
【问题描述】:

我有一个函数,它使用 EF,但它运行得太慢了... 你知道有什么方法,如何提高这个功能的性能吗?

public static void SaveCombiners()
    {
        using (var db = new IP_dbEntities())
        {
            db.COMBINERs.RemoveRange(db.COMBINERs);
            foreach (var type1 in EventTypesList)
            {
                foreach (var type2 in EventTypesList)
                {
                    db.COMBINERs.Add(new COMBINER()
                    {
                        EVENTS_TYPE = db.EVENTS_TYPE.Single(type => type.event_type == type1),
                        EVENTS_TYPE1 = db.EVENTS_TYPE.Single(type => type.event_type == type2),
                        combine_status = _eventTypesCombinerCollection[type1][type2].Value == true ? "+" : "-"
                    });
                }
            }
            db.SaveChanges();
        }
    }

【问题讨论】:

  • 纯SQL写,使用db.Database.ExecuteSqlQuery(sql, params).ToListAsync();
  • 为什么要为 1 个列表写 2 个“Foreach”?
  • 是的,+1,所以您可能会发现更好的是先进行一组读取,然后再进行写入...而不是每次写入时都读取!!!
  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建最小、完整和可验证的示例。
  • 有很多可能的方法可以使您的代码更快,但是当您提供零相关信息时,这是在黑暗中拍摄。也许它很慢,因为您不知道如何正确定义数据库中的索引?为什么你叫 Single 而不是 First...

标签: c# wpf performance entity-framework


【解决方案1】:

您应该始终使用 AddRange 而不是 Add。每次调用 add 方法时 Add 方法都会尝试 DetectChanges,而 AddRange 只调用一次。

public static void SaveCombiners()
{
    using (var db = new IP_dbEntities())
    {
        db.COMBINERs.RemoveRange(db.COMBINERs);

        List<COMBINER> list = new List<COMBINER>();

        foreach (var type1 in EventTypesList)
        {
            foreach (var type2 in EventTypesList)
            {
                list.Add(new COMBINER()
                {
                    EVENTS_TYPE = db.EVENTS_TYPE.Single(type => type.event_type == type1),
                    EVENTS_TYPE1 = db.EVENTS_TYPE.Single(type => type.event_type == type2),
                    combine_status = _eventTypesCombinerCollection[type1][type2].Value == true ? "+" : "-"
                });
            }
        }

        db.COMBINERs.AddRange(list);
        db.SaveChanges();
    }
}

话虽如此,您还面临另一个性能问题。

每条要删除或添加的记录都需要一个数据库往返。因此,如果您删除 10,000 条记录并添加 5,000 条记录,则需要 15,000 次数据库往返,这非常慢。

免责声明:我是项目的所有者Entity Framework Extensions

此库允许您在实体框架中执行批量操作。您只需将“SaveChanges”更改为“BulkSaveChanges”即可显着提高性能。

public static void SaveCombiners()
{
    using (var db = new IP_dbEntities())
    {
        db.COMBINERs.RemoveRange(db.COMBINERs);
        // ... code..
        db.COMBINERs.AddRange(list);

        db.BulkSaveChanges();
    }
}

【讨论】:

    【解决方案2】:

    RemoveRangeAddRange 太慢,试试 ExecuteSqlCommand

    MyContext.Database.ExecuteSqlCommand("Delete from MyTable");
    

    【讨论】:

    • 如果需要删除所有行,这里最好使用“TRUNCATE TABLE [TableName]”命令
    • @AndrewSilver - 也许,但也许不是。截断不会触发触发器,因此应该为 DDL 而不是 DML 保留。
    • 没关系,我用了两次 foreach,因为我的二维字典中有相同的行和列名
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 2015-11-25
    • 2011-11-16
    相关资源
    最近更新 更多