我正在使用Entity Framework v6.1.3并且一个查询正在处理> 10秒从我的应用程序运行。它需要<将AsNoTracking()添加到呼叫时为1:
public IList<Job> GetByERPHeaderIds(string[] headerIds)
{
return base.Query()
.Include(j => j.PreferredBranch)
.Include(j => j.JobType)
.Include(j => j.Technicians)
.Include(j => j.GmcJobStates)
.Where(j => headerIds.Contains(j.ERPServiceOrderId))
.AsNoTracking()
.ToList();
}
GetByERPHeaderIds()方法获取一个包含400个元素的数组。问题是我需要在修改查询检索的一些项后保存回数据库。在我的上下文中,我使用以下代码来管理实体状态:
public virtual void Save(TEntity entity)
{
if (_context.Entry(entity).State == EntityState.Detached)
{
if (entity.IsNew)
{
_dbSet.Add(entity);
}
else
{
var cachedEntity = _dbSet.Local.FirstOrDefault(x => x.Equals(entity));
if (cachedEntity != null)
_context.Entry(cachedEntity).State = EntityState.Detached;
_context.Entry(entity).State = EntityState.Modified;
}
}
else
{
_context.Entry(entity).State = EntityState.Modified;
}
if (!_context.IsUnitOfWorkActive)
{
_context.SaveChanges();
}
}
当我得到&#34;修改&#34;状态实体有时我得到DbUpdateException或有时我得到重复的条目
ex.InnerException.InnerException {&#34;违反PRIMARY KEY约束 &#39; PK_dbo.TechnicianJob&#39 ;.无法在对象中插入重复键 &#39; dbo.TechnicianJob&#39 ;.重复键值为(1039,239)。\ r \ n 语句已被终止。&#34;} System.Exception {System.Data.SqlClient.SqlException}
UPDATE1 : 在这个例子中,我试图保存一个&#34; Job&#34;实体回到数据库。该实体包含对其他表的引用,在本例中是对表&#34; TechnicianJob&#34;的引用。看起来当从数据库中检索分离的实体时,不会正确检索它的表依赖性。我认为这就是我获得该异常的原因,因为它试图保存已存在于数据库中的实体。
UPDATE2 : 这是它在阅读article之后查看我的存储库的方式:
public virtual void Save(TEntity entity)
{
if (_context.Entry(entity).State == EntityState.Detached)
{
if (entity.IsNew)
{
_dbSet.Add(entity);
}
else
{
var cachedEntity = _dbSet.Local.FirstOrDefault(x => x.Equals(entity));
if (cachedEntity != null)
{
var cachedEntry = _context.Entry(cachedEntity);
cachedEntry.CurrentValues.SetValues(entity);
}
else
{
var entry = _context.Entry(entity);
entry.State = EntityState.Modified;
}
}
}
else
{
_context.Entry(entity).State = EntityState.Modified;
}
if (!_context.IsUnitOfWorkActive)
{
_context.SaveChanges();
}
}
答案 0 :(得分:0)
您的通用保存方法取决于更改跟踪。或者至少说实体处于正确的状态。
我建议你在修改它们并调用Save()
之前附加Job实体context.Jobs.Attach(job);
答案 1 :(得分:0)
旅程 为了得到解决方案,我做了一些研究。我发现了使用&#34; AsNoTracking &#34; EF表现非常好。另一方面,您的实体不再被跟踪,除非这些实体与其他表格有关系(我的情况),否则这不应该是一个大问题。通过将实体的状态设置为&#34; Modified&#34;,我能够将实体(即 Job )重新附加到上下文中。然后EF知道它必须对该实体进行更新。 EF不知道如何处理相关实体(即 TechnicianJob )。它一直试图插入它们,最终会出现重复的密钥异常和多个不正确的分配。
我的解决方案 我找到了解决问题的方法。我从我的存储库中删除了急切加载,因此我不强制EF在一个查询中跟踪与其他表的4种不同关系的状态。这将性能从10s提升到100ms。
全球解决方案 看起来非跟踪实体会在EF7中解决,但在发布之前...... GraphDiff:看来这个nuget包提供了非常好的结果,以解决这个不便:
看看此博客描述问题以及如何使用GraphDiff实现解决方案:
Nuget包GraphDiff: