[英]Global setting for AsNoTracking()?
原本我相信
context.Configuration.AutoDetectChangesEnabled = false;
將禁用更改跟蹤。 但不是。 目前我需要在我的所有 LINQ 查詢(對於我的只讀層)上使用AsNoTracking()
)。 是否有禁用 DbContext 跟蹤的全局設置?
簡單地在派生上下文中公開這樣的方法並將其用於查詢怎么樣:
public IQueryable<T> GetQuery<T>() where T : class {
return this.Set<T>().AsNoTracking();
}
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
由於這個問題沒有用特定的 EF 版本標記,我想提一下,在EF Core 中,可以在上下文級別配置行為。
您還可以在上下文實例級別更改默認跟蹤行為:
using (var context = new BloggingContext())
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var blogs = context.Blogs.ToList();
}
在EntityFramework.Core 中,這很容易。
為此,您可以使用UseQueryTrackingBehavior方法。
代碼片段在這里:
services.AddDbContext<DatabaseContext>(options =>
{
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
options.UseSqlServer(databaseSettings.DefaultConnection);
});
你可以在你的 DbContext 中做這樣的事情:
public void ObjectContext_OnObjectMaterialized(Object objSender, ObjectMaterializedEventArgs e)
{
Entry(e.Entity).State = EntityState.Detached;
}
每當一個對象被你的上下文物化時,它就會被分離並且不再被跟蹤。
更新:這並沒有真正奏效。 看評論!
當我在 StackOverflow 上搜索時,我討厭它,答案是:“你不能!” 或者“你可以,但前提是你徹底改變你曾經打過的每一個電話。”
反思任何人? 我希望這將是一個 DbContext 設置。 但由於它不是,我使用反射做了一個。
這個方便的小方法將在 DbSet 類型的所有屬性上設置 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();
}
它使用反射,這意味着有人會很快評論說這是性能下降。 但它真的那么受歡迎嗎? 取決於您的用例。
就我而言,因為我需要將整個上下文設為只讀而不是讀/寫。
因此,我對 tt 文件進行了更改,並將所有 DbContext 屬性更改為返回 DbQuery 而不是 DbSet,從所有屬性中刪除了集合,對於獲取,我返回了 Model.AsNoTracking()
例如:
public virtual DbQuery<Campaign> Campaigns { get{ return Set<Campaign>().AsNoTracking();} }
我在 tt 模板中這樣做的方式是:
public string DbQuery(EntitySet entitySet) { return string.Format( CultureInfo.InvariantCulture, "{0} virtual DbQuery<{1}> {2} {{ get{{ return Set<{1}>().AsNoTracking();}} }}", Accessibility.ForReadOnlyProperty(entitySet), _typeMapper.GetTypeName(entitySet.ElementType), _code.Escape(entitySet)); }
如果使用實體框架核心,您還可以在繼承 DbContext 的類的構造函數中添加以下代碼。
public NPCContext()
: base()
{
base.ChangeTracker.AutoDetectChangesEnabled = false;
}
或以下
public NPCContext(DbContextOptions<NPCContext> options)
: base(options)
{
base.ChangeTracker.AutoDetectChangesEnabled = false;
}
您可以使用以下代碼片段作為參考
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
請注意,在 EF Core 5.0 之前,無法使用“無跟蹤”啟用身份解析。 但是現在,使用 EF Core 5.0,可以使用額外的 API 來啟用“無跟蹤”和身份解析。 因此,如果您想通過身份解析“不跟蹤”,那么在 EF Core 5.0 中使用以下代碼段
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTrackingWithIdentityResolution);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.