あなたの質問に対する直接的な回答ではありませんが、DbSet でアクセスできない MergeOption に関する EF の監視に対する T4 ベースの解決策を考え出しました。あなたの質問から、これはあなたが探しているものだと思われますか?
デフォルトのコンテキストには、次のような T4 ジェネレーターによって生成されたものがあります。
public virtual DbSet<Person> Persons { get; set; }
public virtual DbSet<Address> Addresses { get; set; }
等
私のアプローチは、T4 を編集して、IQueryable として ObjectSet に直接アクセスできる各エンティティに 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 でリロードして、最新のエンティティを確実に取得する必要があることです。