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

时间:2016-01-23 18:26:59

标签: c# entity-framework

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

 _context.Set<Entity>().AsNoTracking().Find(id);

我该怎么做?我正在使用EF版本6。

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

4 个答案:

答案 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的唯一选择是WhereFirstSingle...

答案 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();