ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 为什么Entity Framework在一个SaveChanges()中添加多个项目这么慢?

2019-06-08 08:02:08  阅读:281  来源: 互联网

标签:c entity-framework entity-framework-6


这是a previous question的后续工作,其中我试图弄清楚我的代码运行缓慢的主要原因.我想我已经把它缩小到下面的一个最小例子.我有一个基本的数据库结构如下:

public class Foo
{
    public int Id { get; set; }
    public string Bar { get; set; }
}

public class FooContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }
}

现在,如果我有一个Foo对象列表,并希望将它们添加到数据库,建议的方法是使用AddRange().但是我注意到它花了很长时间,并且受到集合中项目数量的影响很小,即使是200这样的少量.所以我手动编写了它,并且中提琴,它运行得更快!

class Program
{
    static void Main(string[] args)
    {
        var foos = Enumerable.Range(0, 200).Select(index => new Foo { Bar = index.ToString() });

        // Make sure the timing doesn't include the first connection
        using (var context = new FooContext())
        {
            context.Database.Connection.Open();
        }

        var s1 = Stopwatch.StartNew();
        using (var context = new FooContext())
        {
            context.Foos.AddRange(foos);
            context.SaveChanges();
        }
        s1.Stop();

        var s2 = Stopwatch.StartNew();
        using (var context = new FooContext())
        {
            // Ignore the lack of sanitization, this is for demonstration purposes
            var query = string.Join(";\n", foos.Select(f => "INSERT INTO Foos ([Bar]) VALUES (" + f.Bar + ")"));
            context.Database.ExecuteSqlCommand(query);
        }
        s2.Stop();

        Console.WriteLine("Normal way: {0}", s1.Elapsed);
        Console.WriteLine("Hard way  : {0}", s2.Elapsed);
        Console.ReadKey();
    }
}

我最初的想法是,实体框架可能正在为每个条目使用单独的事务,但是记录SQL显示情况并非如此.那为什么执行时间会有这么大差异呢?

解决方法:

在对您的问题进行一些研究时,我偶然发现了这篇具有启发性的文章:http://www.codinghelmet.com/?path=howto/bulk-insert

这是一个引用:

Each object that was inserted required two SQL statements – one to insert a record, and additional one to obtain identity of the new record

插入多个记录时会出现问题.每个记录一次插入一个事实会加剧一个问题(但是这已经超出了你的问题的上下文,因为你已经在逐个插入测试).因此,如果您要插入200条记录,则会逐个执行400条sql语句.

所以根据我的理解,EF根本不是为批量插入而构建的.即使它像插入200条记录一样简单.这对我来说似乎是一个很大的失望.

我开始思考,“那么EF无论如何都是好事.它甚至不能插入几条记录”.那么我会在两个方面给EF道具:

>选择查询:编写查询并快速将数据导入应用程序非常容易.
>简化复杂记录的插入.如果您曾经拥有一张包含大量外键的表,并且您尝试在一次交易中插入所有链接的记录,那么您就知道我在说什么.值得庆幸的是,EF按顺序插入每条记录,并在一次交易中为您链接所有相关记录.但如上所述,这需要付出代价.

所以简单地说,似乎,如果你有一个需要插入一堆记录的操作,最好使用SqlBulkCopy.这可以在几秒钟内插入数千条记录.

我知道这可能不是你想听到的答案,因为相信我,因为我使用了很多EF,所以它也让我感到不安,但是我没有看到任何解决方法

标签:c,entity-framework,entity-framework-6
来源: https://codeday.me/bug/20190608/1196509.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有