AsNoTracking()的全局设置?

原来我是这么认为的

context.Configuration.AutoDetectChangesEnabled = false; 

将禁用更改跟踪。 但不是。 目前,我需要在我的所有LINQ查询(对于我的只读图层)上使用AsNoTracking() )。 是否有全局设置禁用DbContext的跟踪?

由于这个问题没有用特定的EF版本标记,所以我想提到在EF Core中 ,行为可以在上下文级别进行configuration 。

您还可以在上下文实例级别更改默认的跟踪行为:

 using (var context = new BloggingContext()) { context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var blogs = context.Blogs.ToList(); } 

那么简单地在你的派生上下文中暴露这样的方法,并将其用于查询:

 public IQueryable<T> GetQuery<T>() where T : class { return this.Set<T>().AsNoTracking(); } 

在全球设置AsNoTracking是不可能的。 您必须对每个查询或每个ObjectSet (而不是DbSet )进行设置。 后一种方法需要使用ObjectContext API。

 var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; var set = objectContext.CreateObjectSet<T>(); set.MergeOption = MergeOption.NoTracking; // And use set for queries 

你可以在你的DbContext中做这样的事情:

 public void ObjectContext_OnObjectMaterialized(Object objSender, ObjectMaterializedEventArgs e) { Entry(e.Entity).State = EntityState.Detached; } 

每当一个对象被你的上下文实现时,它就会被分离,不再被跟踪。

更新:这并没有真正的工作。 看评论!

我讨厌它,当我searchStackOverflow的答案是:“你不能!” 或者“你可以,但只有当你完全改变你所做过的每一个电话”。

反思任何人? 我希望这将是一个DbContext设置。 但是既然不是这样,我就用反思做了一个。

这个方便的小方法将在DbSettypes的所有属性上设置AsNoTracking。

  private void GloballySetAsNoTracking() { var dbSetProperties = GetType().GetProperties(); foreach (PropertyInfo pi in dbSetProperties) { var obj = pi.GetValue(this, null); if (obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(DbSet<>)) { var mi = obj.GetType().GetMethod("AsNoTracking"); mi.Invoke(obj, null); } } } 

将其添加到重载的DbContext构造函数中。

  public ActivationDbContext(bool proxyCreationEnabled, bool lazyLoadingEnabled = true, bool asNoTracking = true) { Configuration.ProxyCreationEnabled = proxyCreationEnabled; Configuration.LazyLoadingEnabled = lazyLoadingEnabled; if (asNoTracking) GloballySetAsNoTracking(); } 

它使用reflection,这意味着有人会很快评论这是一个性能问题。 但这真的是一个打击? 取决于你的用例。

在我的情况下,因为我需要整个上下文是只读而不是读/写。

所以我做了一个tt文件的更改,并且改变了所有的DbContext属性来返回DbQuery而不是DbSet,从所有的属性中移除了这些集合,为了得到,我返回了Model.AsNoTracking()

例如:

 public virtual DbQuery<Campaign> Campaigns { get{ return Set<Campaign>().AsNoTracking();} }