Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架5表现不佳_C#_Entity Framework_Entity Framework 5 - Fatal编程技术网

C# 实体框架5表现不佳

C# 实体框架5表现不佳,c#,entity-framework,entity-framework-5,C#,Entity Framework,Entity Framework 5,我有5个实体: public class Album { public int Id { get; set; } public string Title { get; set; } public virtual List<AlbumArtist> AlbumArtists { get; set; } public virtual List<Artist> Artists { get; set; } public virtual

我有5个实体:

public class Album
{
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual List<AlbumArtist> AlbumArtists { get; set; }
    public virtual List<Artist> Artists { get; set; }
    public virtual List<Genre> Genres { get; set; }
    public virtual List<Song> Songs { get; set; }

}

public class AlbumArtist
{
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual List<Album> Albums { get; set; }
    public virtual List<Artist> Artists { get; set; }
    public virtual List<Genre> Genres { get; set; }
    public virtual List<Song> Songs { get; set; }
}

public class Artist
{
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual List<AlbumArtist> AlbumArtists { get; set; }
    public virtual List<Album> Albums { get; set; }
    public virtual List<Genre> Genres { get; set; }
    public virtual List<Song> Songs { get; set; }
}

public class Genre
{
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual List<AlbumArtist> AlbumArtists { get; set; }
    public virtual List<Album> Albums { get; set; }
    public virtual List<Artist> Artists { get; set; }
    public virtual List<Song> Songs { get; set; }
}

public class Song
{
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual List<AlbumArtist> AlbumArtists { get; set; }
    public virtual List<Album> Albums { get; set; }
    public virtual List<Artist> Artists { get; set; }
    public virtual List<Genre> Genres { get; set; }
}
或者以这种方式:

_albumArtists.ForEach(delegate(AlbumArtist albumArtist)
{
    if (albumArtist.Id == 0)
    {
            _dbContext.Entry(entity).State = EntityState.Added;
            _dbContext.SaveChanges();
    }
    else
    {
            _dbContext.Entry(entity).State = EntityState.Modified;
            _dbContext.SaveChanges();
    }
});
...
_albumArtists.ForEach(delegate(AlbumArtist albumArtist)
{
    if (albumArtist.Id == 0)
    {
            _dbContext.Entry(entity).State = EntityState.Added;
    }
    else
    {
            _dbContext.AlbumArtists.State = EntityState.Modified;
    }
});
_dbContext.SaveChanges();
...
将实体保存到DbContext需要花费很长时间。我甚至试着做了以下几件事:

Configuration.AutoDetectChangesEnabled = false;
但这没用。顺便说一下,大约有17000首歌曲和1700张专辑

怎么了

请帮忙

PS

这是我的全部代码: 也许你可以建议如何简化它


谢谢

首先要澄清几点:

对于基于批处理的操作,EF并不比其他方法慢很多。在我的测试中,使用原始SQL命令可能会提高50%,使用SQL大容量复制可能会提高10倍,但作为一般规则,EF并不比比较方法慢多少(尽管通常被认为非常慢)。对于大多数应用程序,EF将给出适当的性能数字,即使在正确调整的批量场景中也是如此。(见我的文章:和)

由于EF进行更改跟踪的方式,其性能可能远远超过大多数人编写基于SqlCommand的insert语句的性能(在查询规划、往返和事务方面有很多问题,使得编写性能最佳的批量insert语句非常困难)。我已经在这里提出了对EF()的这些添加,但是还没有实现它们

您关闭自动检测更改的决定完全正确,每个.Add或.Attach操作都会枚举跟踪图,因此,如果您在同一上下文中添加17k个添加项,则需要在总计17000+16999+…+2+1=144500000个实体上枚举图17000次,难怪要花这么长时间,对吧?(见我的文章:)

保存更改总是需要枚举跟踪图(它在内部调用detect changes),因此您的第一种方法会很慢,因为它实际上会执行与上面相同数量的跟踪调用

第二种方法要好得多,但它仍然有一个相当大的缺陷,我认为这有两个方面,第一,当你去保存更改时,图形确实很大(较大的图形具有指数级的更高跟踪时间),其次,一次保存整个图形需要占用大量内存,特别是考虑到EF存储每个实体的两个副本

更好的方法是将图形持久化为块。一些

//With Auto detect changes off.
foreach(var batch in batches)//keep batch size below 1000 items, play around with the numbers a little
{
    using(var ctx = new MyContext())//make sure you create a new context per batch.
    {
        foreach(var entity in batch){
             ctx.Entities.Add(entity);
        }
        ctx.SaveChanges();
    }
}
我想你应该瞄准17-30秒来完成所有17k行

通过使用原始SQL命令执行此操作,您可以将其设置为12-20秒左右


通过批量复制的重新实现,您可能需要花费一些时间才能节省17000首歌曲和1700张专辑,节省2-5秒。如果您只是修改其中的一部分,则不应花费太长时间。我无法从您的代码中判断
\u
是否包含所有内容,还是仅包含修改/添加的内容。是否有原因不能让自动更改检测来判断您是否已更改内容?这将更简单,并确保您不会重新保存不需要的内容。\u AlbumArtisters包含所有。。。大约需要4个小时!怎么做?谢谢实体框架(以及通常的ORM)不打算用于大规模批量操作。创建一个纯SQL脚本来插入数据,然后用ORM执行每日1记录操作。我可以保证实体框架的性能不会那么差,至少这是根本原因。是的,速度较慢,但归根结底,这取决于您自己处理数据的方法。我的任务是重新编写我们公司的一个批导入过程(我们每晚都在谈论数十万条记录),起初我没有意识到实体框架对性能的影响,但经过大量的调整后,我能够让它运行得相当快。事实证明,由于我处理数据的方式,我的版本比使用纯SQL的旧版本快。总有更多的事情要做it@DavidAnderson-DCOM与所有框架一样,有好的方法也有坏的方法,很多人并不真正了解EF的幕后运作,这可能会鼓励他们使用一些糟糕的方式做事,但这并不意味着整个框架很慢:)当我第一次对你的“关闭”->“关闭”进行EF调优时,我有一个非常类似的故事?