私は少し困惑しています。私が読んだものからDbContext.AutoDetectChangesEnabled
をfalse
に設定すると、データベースに送信される変更を識別するためにDbContext.DetectChanges
を呼び出す必要がある変更追跡が無効になります。
ただし、以下のログから、設定がfalseに設定されていても、dbContexts変更トラッカーによって変更が登録されていることがわかります。
何か不足していますか?
Entity Frameworkバージョン:5.0.0.0
DbContextクラス
public class ProjectContext : DbContext {
public DbSet<Project> Projects {get;set;}
}
コントローラークラス
private ProjectContext db = new ProjectContext();
public method(){
Project p = new Project("uniqueName");
db.Configuration.AutoDetectChangesEnabled = false;
db.Projects.Add(p);
DebugChangeTracker();
db.SaveChanges();
db.Projects.First().ProjectName = "a differentName!";
DebugChangeTracker();
db.SaveChanges();
}
ロギング方法
private void DebugChangeTracker()
{
var path = "C:\\mypath\\";
path = path + Util.GetMsSinceEpoch().ToString() + "changeTracker.log";
using (StreamWriter sw = new StreamWriter(path))
{
var changeTracker = db.ChangeTracker;
var entries = changeTracker.Entries();
foreach (var x in entries)
{
var name = x.Entity.ToString();
var state = x.State;
sw.WriteLine("");
sw.WriteLine("***Entity Name: " + name +
"is in a state of " + state);
var currentValues = x.CurrentValues;
sw.WriteLine("***CurrentValues***");
PrintPropertyValues(currentValues,sw);
if (state != EntityState.Added)
{
sw.WriteLine("***Original Values***");
PrintPropertyValues(x.OriginalValues,sw);
}
}
}
}
最初のログ
***Entity Name: Models.Projectis in a state of Added
***CurrentValues***
ProjectId:0
ProjectName:uniqueName
2番目のログ
***Entity Name: Models.Projectis in a state of Modified
***CurrentValues***
ProjectId:1
ProjectName:uniqueName
***Original Values***
ProjectId:1
ProjectName:a differentName!
AutoDetectChangesEnabled
をfalse
に設定しても、変更追跡は無効になりません。 (これがAsNoTracking()
拡張メソッドが行うことです。)それは、そうでなければ多くのDetectChanges
APIメソッドで発生するDbContext
の自動呼び出しを無効にします。
ただし、DetectChanges
は変更追跡に参加する唯一の方法ではありません。ただし、必要な適切な場所で手動で呼び出さないと、追跡されたエンティティの状態が不完全または間違っているため、データが誤って保存されます。
あなたの場合、Added
はmethod
に設定されている場合でも、db.Projects.Add(p)
のみを呼び出すため、AutoDetectChangesEnabled
の最初の部分の状態false
が期待されます。 (コードに行がありませんが、コピーアンドペーストのエラーだと思います。)DbContext
APIからメソッドを呼び出すと、変更が正しく追跡され、状態が正しい場合はトラッカーの状態が正しくなります。 Add
の呼び出し前。
または言い換えると、APIメソッドを呼び出しても、正しい状態が間違った状態に変わることはありません。しかし:AutoDetectChangesEnabled
がfalse
である場合、AutoDetectChangesEnabled
がtrue
である場合に、間違った状態を正しい状態に変えることもありません。
ただし、method
の2番目の部分では、POCOプロパティ値を変更しているだけです。この時点の後、変更トラッカーの状態は間違っています(Unchanged
)、DetectChanges
への呼び出しなし(手動または-AutoDetectChangesEnabled
がtrue
の場合-ChangeTracker.Entries
で自動的にまたはSaveChanges
)調整されることはありません。その結果、変更されたプロパティ値はデータベースに保存されません。
最後のセクションでUnchanged
状態について言及しているので、私は自分のテスト(および予想されるもの)について言及しています。 Modified
状態になっている理由がわかりません。再現できません。
申し訳ありませんが、これが少しわかりにくい場合は。 アーサー・ビッカーズはそれをより良く説明できます。
無効にするときの自動変更検出と動作を理解し、習得するのはかなり難しく、通常、追跡された変更よりも複雑な変更のデフォルト(AutoDetectChangesEnabled
= true
)には触れません。最も単純なもの(ループ内でのエンティティの一括追加など)。
Entity Framework CoreでAutoDetectChangesEnabled
を探している人は、ChangeTracker
insted of Configuration
の下で見つけることができます
次のような使用法:
context.ChangeTracker.AutoDetectChangesEnabled = false;
//Do something here
context.PriceRecords.Add(newPriceRecord);
context.ChangeTracker.AutoDetectChangesEnabled = true;
エンティティによる フレームワークの自動変更の記事の検出
彼らは言った:
大幅に改善される可能性がありますパフォーマンスの改善有効にするとoffで
some cases
その記事からこの例を見てください
using (var context = new BloggingContext())
{
try
{
context.Configuration.AutoDetectChangesEnabled = false;
// Make many calls in a loop
foreach (var blog in aLotOfBlogs)
{
context.Blogs.Add(blog);
}
}
finally
{
context.Configuration.AutoDetectChangesEnabled = true;
}
}
このコードは、DbSet.Add
およびDetectChanges
メソッドの呼び出し中に発生するSaveChanges
への不要な呼び出しを回避します。