如何在对EF上下文进行查询时将Find()
与AsNoTracking()
结合使用,以防止跟踪返回的对象。这是我不能做的事情
_context.Set<Entity>().AsNoTracking().Find(id);
我该怎么做?我正在使用EF版本6。
注意:我不想使用SingleOrDefault()
或Where
。我只是不能,因为参数Id
是通用的,它是struct
,在这种情况下我不能将算子==
应用于泛型。
答案 0 :(得分:17)
因此,您可以执行AsNoTracking()
而不是使用Find()
,然后将其与上下文分离。我相信除了获得实体跟踪的额外开销之外,这会给你带来与AsNoTracking()
相同的结果。有关详细信息,请参阅EntityState。
var entity = Context.Set<T>().Find(id);
Context.Entry(entity).State = EntityState.Detached;
return entity;
编辑:这有一些潜在的问题,如果上下文没有加载某些关系,那么这些导航属性将无法工作,你会感到困惑和沮丧为什么一切都返回null!有关详细信息,请参阅https://stackoverflow.com/a/10343174/2558743。就目前这些存储库而言,我正在覆盖我需要的存储库中的FindNoTracking()
方法。
答案 1 :(得分:7)
<context>.<Entity>.AsNoTracking().Where(s => s.Id == id);
{p> Find()
对AsNoTracking()
没有意义,因为Find
应该能够返回跟踪的实体而无需转到数据库.. AsNoTracking
的唯一选择是Where
或First
或Single...
答案 2 :(得分:1)
好吧,我想如果你真的想这样做,你可以尝试自己创建你的表达。我假设你有一个通用的基本实体类,这是通用键属性的来源。我将该类命名为KeyedEntityBase<TKey>
,TKey
是键的类型(如果您没有这样的类,那很好,我使用的唯一的东西是泛型约束)。然后你可以创建一个像这样的扩展方法来自己构建表达式:
public static class Extensions
{
public static IQueryable<TEntity> WhereIdEquals<TEntity, TKey>(
this IQueryable<TEntity> source,
Expression<Func<TEntity, TKey>> keyExpression,
TKey otherKeyValue)
where TEntity : KeyedEntityBase<TKey>
{
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<Func<TEntity, bool>>(equal, parameter);
return source.Where(lambda);
}
}
然后,您可以像这样使用它(对于整数键类型):
context.Set<MyEntity>.AsNoTracking().WhereIdEquals(m=>m.Id, 9).ToList();
答案 3 :(得分:-1)
要复制Find
和/或FindAsync
的行为,
您可以使用:
_context.EntitySet.FirstOrDefault(x => x.id == id).AsNoTracking();