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();} }