.net 实体框架6-附加使用AsNoTracking查询的实体图

.net 实体框架6-附加使用AsNoTracking查询的实体图,.net,sql-server,entity-framework,entity-framework-6,ef-code-first,.net,Sql Server,Entity Framework,Entity Framework 6,Ef Code First,我正在从FattureFornitori表中检索实体列表,并加载它们拥有的集合Voci、复数形式-Voce、单数形式以及每个Voce对TipoCosto实体的引用: 现在,一个FattureFornitori中的多个Voci可以引用相同的TipoCosto。 因此,当我尝试附加一个FattureFornitori及其Voci和引用的TipoCosto时,我面临以下错误: System.InvalidOperationException: 'Attaching an entity of type

我正在从FattureFornitori表中检索实体列表,并加载它们拥有的集合Voci、复数形式-Voce、单数形式以及每个Voce对TipoCosto实体的引用:

现在,一个FattureFornitori中的多个Voci可以引用相同的TipoCosto。 因此,当我尝试附加一个FattureFornitori及其Voci和引用的TipoCosto时,我面临以下错误:

System.InvalidOperationException: 'Attaching an entity of type 'GP.Model.TipoCosto' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.'
对一个名为ff的FattureFornitori实体进行的一些调试显示:

ff.Voci[1].IdTipoCosto == ff.Voci[0].IdTipoCosto
true
ff.Voci[1].TipoCosto == ff.Voci[0].TipoCosto
false
所以实体框架为同一实体创建多个实例!因此,attach方法引起的错误是有意义的。 但如何解决这种情况呢?? 我照看GraphDiff和其他类似的工具,但它们帮不上忙。 有什么提示吗?
谢谢

正如格特·阿诺德(Gert Arnold)所建议的,一个解决办法是删除AsNoTracking。 但这意味着数据库上下文将把所有实体添加到被跟踪的实体中,因此它的性能会很差

我尝试了以下代码:

var db = new DbGestPre();
db.Configuration.ProxyCreationEnabled = false;
db.Configuration.AutoDetectChangesEnabled = false;
var s = db.FattureFornitori
                .Include(x => x.Fornitore)
                .Include(x => x.Voci)
                .Include(x => x.Voci.Select(y => y.TipoCosto));
List<FatturaFornitore> data = s.ToList();
db.Dispose();
为了快速从上下文中分离实体,我处理了上下文。欢迎任何更快/更好的方法。 此代码以858毫秒的速度运行

我以前的选择

var db = new DbGestPre();
db.Configuration.ProxyCreationEnabled = false;
var s = db.FattureFornitori
                .Include(x => x.Fornitore)
                .Include(x => x.Voci)
                .Include(x => x.Voci.Select(y => y.TipoCosto))
                .AsNoTracking();
List<FatturaFornitore> data = s.ToList();
只跑了500毫秒


因此,我仍在寻找一种方法,使这个版本的代码与AsNoTracking一起工作。

删除AsNoTracking。然后EF将创建唯一的TipoCosto实例。但我不希望EF跟踪这些实体,也不希望它创建代理。我需要尽可能地执行最轻量级的操作。只是删除AsNoTracking使生活更轻松。顺便说一下,它不需要创建代理。如果它不会对性能造成太大影响,我会选择它。由于AsNoTracking,您需要的任何重复数据消除代码很有可能需要358毫秒以上。我认为使用AutoDetectChangesEnabled=false的替代方法是您能得到的最好方法。@GertArnold您能详细说明一下吗?我不明白,AsNoTracking的代码需要一个重复数据消除步骤,不是吗?*实体框架为同一实体创建多个实例!*。我想知道这是否能在858-500=385毫秒内完成。哦,好吧,现在我明白了!:当然可以。
var db = new DbGestPre();
db.Configuration.ProxyCreationEnabled = false;
var s = db.FattureFornitori
                .Include(x => x.Fornitore)
                .Include(x => x.Voci)
                .Include(x => x.Voci.Select(y => y.TipoCosto))
                .AsNoTracking();
List<FatturaFornitore> data = s.ToList();