尽管不是您问题的直接答案,但我提出了一个基于 T4 的解决方案,用于解决在 DbSet 中无法访问 MergeOption 的 EF 监督问题。从您的问题看来,这就是您要寻找的东西?
在默认上下文中,您有一些由 T4 生成器生成的内容,例如:
public virtual DbSet<Person> Persons { get; set; }
public virtual DbSet<Address> Addresses { get; set; }
等等
我的方法是编辑 T4 为每个提供直接访问 ObjectSet 作为 IQueryable 的实体添加 Getter:
public IQueryable<Person> GetPersons(MergeOption mergeOption = MergeOption.AppendOnly, bool useQueryImplentation = true)
{
return useQueryImplementation ? GetSet<Person>(mergeOption).QueryImplementation() : GetSet<Person>(mergeOption);
}
然后在一个基本的 DataContext
public class DataContextBase
{
/// <summary>
/// Gets or sets the forced MergeOption. When this is set all queries
/// generated using GetObjectSet will use this value
/// </summary>
public MergeOption? MergeOption { get; set; }
/// <summary>
/// Gets an ObjectSet of type T optionally providing a MergeOption.
/// <remarks>Warning: if a DataContext.MergeOption is specified it will take precedence over the passed value</remarks>
/// </summary>
/// <typeparam name="TEntity">ObjectSet entity Type</typeparam>
/// <param name="mergeOption">The MergeOption for the query (overriden by DataContext.MergeOption)</param>
protected IQueryable<TEntity> GetObjectSet<TEntity>(MergeOption? mergeOption = null) where TEntity : class
{
var set = Context.CreateObjectSet<TEntity>();
set.MergeOption = MergeOption ?? mergeOption ?? MergeOption.AppendOnly;
return set;
}
通过为 IQueryable 创建一个默认的扩展方法,如下所示,您可以选择为每个表/类型添加您自己的 QueryImplementation 实现,以便您的表的所有用户都可以排序或包含等(这部分不是回答问题所必需的,但它反正有用)
因此,例如,您可以在调用 GetPersons() 时添加以下内容以始终包含地址
public static class CustomQueryImplentations
{
public static IQueryable<Person> QueryImplementation(this IQueryable<Person> source)
{
return source
.Include(r => r.Addresses)
.OrderByDescending(c => c.Name);
}
}
最后:
//just load a simple list with no tracking (Fast!)
var people = Database.GetPersons(MergeOption.NoTracking);
//user wants to edit Person so now need Attached Tracked Person (Slow)
var peson = Database.GetPersons(MergeOption.OverwriteChanges).FirstOrDefault(p => p.PersonID = 1);
//user makes changes and on another machine sometime later user clicks refresh
var people = Database.GetPersons(MergeOption.OverwriteChanges);
或者你可以(就像我一样)写一些像
Database.MergeOption = MergeOption.OverwriteChanges;
使用现有的 Get 方法刷新实体负载,但现在将全部覆盖附加实体
Database.MergeOption = null;
需要注意的是,如果您在进行更改之前加载 AsNoTracking,则需要重新附加或使用 OverwriteChanges 更好地重新加载,以确保您拥有最新的实体。