如何结合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
的唯一选择是Where
或First
或Single...
好吧,我想如果你真的想这样做,你可以尝试自己创建你的表达。 我假设你有一个通用的基本实体类,这是通用键属性的来源。 我将该类命名为KeyedEntityBase
, TKey
是键的类型(如果您没有这样的类,那很好,我使用的唯一的东西是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();