如何结合Find()和AsNoTracking()?

如何在对EF上下文进行查询时将Find()AsNoTracking()结合使用,以防止跟踪返回的对象。 这是我不能做的

  _context.Set().AsNoTracking().Find(id); 

我怎样才能做到这一点? 我使用EF版本6。

注意:我不想使用SingleOrDefault()Where 。 我只是不能,因为参数Id是通用的,它是一个struct ,在这种情况下我不能将operator ==应用于generics。

因此,您可以执行Find() ,然后将其与上下文分离,而不是使用AsNoTracking() 。 我相信这会给你带来与AsNoTracking()相同的结果,除了获得实体跟踪的额外开销。 有关更多信息,请参阅EntityState 。

 var entity = Context.Set().Find(id); Context.Entry(entity).State = EntityState.Detached; return entity; 

编辑:这有一些潜在的问题,如果上下文没有加载某些关系,那么这些导航属性将无法工作,你会感到困惑和沮丧为什么一切都返回null! 有关详细信息,请参阅https://stackoverflow.com/a/10343174/2558743 。 现在在这些存储库中,我正在覆盖我需要的存储库中的FindNoTracking()方法。

 ..AsNoTracking().Where(s => s.Id == id); 

使用AsNoTracking() Find()没有意义,因为Find应该能够返回被跟踪的实体而无需进入数据库..您使用AsNoTracking的唯一选择是WhereFirstSingle...

好吧,我想如果你真的想这样做,你可以尝试自己创建你的表达。 我假设你有一个通用的基本实体类,这是通用键属性的来源。 我将该类命名为KeyedEntityBaseTKey是键的类型(如果您没有这样的类,那很好,我使用的唯一的东西是generics约束)。 然后你可以创建这样的扩展方法来自己构建表达式:

 public static class Extensions { public static IQueryable WhereIdEquals( this IQueryable source, Expression> keyExpression, TKey otherKeyValue) where TEntity : KeyedEntityBase { var memberExpression = (MemberExpression)keyExpression.Body; var parameter = Expression.Parameter(typeof(TEntity), "x"); var property = Expression.Property(parameter, memberExpression.Member.Name); var equal = Expression.Equal(property, Expression.Constant(otherKeyValue)); var lambda = Expression.Lambda>(equal, parameter); return source.Where(lambda); } } 

然后,您可以像这样使用它(对于整数键类型):

 context.Set.AsNoTracking().WhereIdEquals(m=>m.Id, 9).ToList();