2013-05-31 4 views
28

मैं थोड़ा स्टंप हूं। मैंने जो कुछ पढ़ा है, उससे डीबीसीएन्टेक्स्ट.एटोडेटेक्ट चेंज को गलत पर सेट करने से परिवर्तन ट्रैकिंग को अक्षम करना चाहिए, जिसे डेटाबेस में भेजे जाने वाले परिवर्तनों की पहचान करने के लिए DbContext.DetectChanges को कॉल करने की आवश्यकता होती है।DbContext AutoDetectChangesEnabled को झूठी पहचान करने के लिए सेट

हालांकि, यह नीचे मेरे लॉग से स्पष्ट है कि परिवर्तन dbContexts द्वारा ट्रैक किया जा रहा है, यहां तक ​​कि सेटिंग को झूठी सेट के साथ भी बदल दिया जा रहा है।

क्या मुझे कुछ याद आ रही है?

इकाई की रूपरेखा संस्करण: 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 

दूसरा लॉग

***Entity Name: Models.Projectis in a state of Modified 
***CurrentValues*** 
ProjectId:1 
ProjectName:uniqueName 
***Original Values*** 
ProjectId:1 
ProjectName:a differentName! 

उत्तर

38

स्थापना false करने के लिए AutoDetectChangesEnabled परिवर्तन ट्रैकिंग अक्षम नहीं है। (यही AsNoTracking() एक्सटेंशन विधि करेगा।) यह केवल DetectChanges की स्वचालित कॉल को अक्षम करता है जो अन्यथा DbContext API विधियों में होता है।

लेकिन DetectChanges एकमात्र तरीका नहीं है जो परिवर्तन ट्रैकिंग में भाग लेता है। हालांकि, अगर आप इसे सही जगहों पर मैन्युअल रूप से कॉल नहीं करते हैं जहां इसकी आवश्यकता होती है तो ट्रैक की गई इकाई के राज्य अपूर्ण या गलत हैं जो गलत तरीके से सहेजे गए डेटा की ओर अग्रसर हैं।

आपके मामले में अपने method के पहले भाग में राज्य Added की उम्मीद है, यहां तक ​​कि false करने के लिए AutoDetectChangesEnabled सेट के साथ क्योंकि आप केवल db.Projects.Add(p) कहते हैं। (लाइन आपके कोड बीटीडब्ल्यू में गायब है, लेकिन मुझे लगता है कि यह सिर्फ एक कॉपी और पेस्ट त्रुटि है।) DbContext एपीआई से एक विधि को कॉल करना एपीआई ट्रैक सही ढंग से बदलता है और कॉलर से राज्य सही होगा अगर कॉल करने से पहले राज्य सही था Add

या दूसरे शब्दों में: एक एपीआई विधि को कॉल करना सही स्थिति को गलत स्थिति में नहीं बदलता है। लेकिन: यदि AutoDetectChangesEnabledfalse है तो यह गलत स्थिति को सही स्थिति में नहीं बदलेगा, यदि AutoDetectChangesEnabledtrue है तो यह मामला होगा।

हालांकि, आपके method के दूसरे भाग में आप केवल एक पीओसीओ संपत्ति मूल्य बदल रहे हैं। इस बिंदु के बाद परिवर्तन ट्रैकर स्थिति गलत है (Unchanged) और DetectChanges पर कॉल किए बिना (मैन्युअल रूप से या - AutoDetectChangesEnabledtrue है - स्वचालित रूप से ChangeTracker.Entries या SaveChanges में) इसे कभी भी समायोजित नहीं किया जाएगा। प्रभाव यह है कि परिवर्तित संपत्ति मान डेटाबेस में सहेजा नहीं जाता है।

अंतिम खंड में राज्य Unchanged का उल्लेख करते हुए मैं अपने स्वयं के परीक्षण (और जो भी मैं उम्मीद करता हूं) का जिक्र कर रहा हूं। मैं नहीं जानता और पुन: पेश नहीं कर सकता कि आपके पास Modified क्यों है।

क्षमा करें, अगर यह सब कुछ उलझन में लगता है। Arthur Vickers can explain it better.

मैं स्वत: परिवर्तन का पता लगाने और व्यवहार जब उसे अक्षम करना नहीं बल्कि मुश्किल समझने के लिए और गुरु और मैं आमतौर पर डिफ़ॉल्ट (AutoDetectChangesEnabled = true) को स्पर्श नहीं करते किसी भी परिवर्तन को सरल बातें की तुलना में अधिक जटिल हैं पर नज़र रखी के लिए (एक लूप, आदि में थोक जोड़ने इकाइयों की तरह)।

+0

मुझे लगता है कि कुछ समय से अधिक पढ़ने के लिए था, लेकिन उत्तर देने में सहायता करता है मेरी सवाल थोड़ा सा, धन्यवाद! कॉपी और पेस्ट त्रुटि के बारे में खेद है; मैं जनसंख्या के लिए सवाल अद्यतन करूंगा। – Jesse

+1

दुर्भाग्यवश, "एक लूप में थोक जोड़ना इकाइयां", जब आप परिवर्तन ट्रैकिंग अक्षम करना चाहते हैं। यह _massive_ speedup (1 का नमूना आकार, मेरे ऐप में परीक्षण किया गया है, लेकिन यह ~ 3000 पंक्तियों को जोड़कर दो रनों के बीच एकमात्र अंतर था)। –

+1

@EdS .: थोक जोड़ना "सबसे सरल चीजों" में से एक है जिसका अर्थ है कि मैं वास्तव में * स्वचालित परिवर्तन पहचान अक्षम कर दूंगा। – Slauma

1

इकाई Framework Automatic Detect Changes's Article

के अनुसार उन्होंने कहा:

आप इसे उस लेख से इस उदाहरण को में 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; 
    } 
} 

यह कोड DetectChanges पर अनावश्यक कॉल से बचाता है जो DbSet.Add और SaveChanges विधियों को कॉल करते समय हुआ होगा।

+0

यदि आप इसे अंततः ब्लॉक में चालू करते हैं, तो यह स्वचालित रूप से करता है ऐसा करें जो यह किया गया था अगर यह चालू था लेकिन जल्दी? –

2

किसी इकाई की रूपरेखा कोर में AutoDetectChangesEnabled की तलाश में आप ChangeTracker अंतर्गत देख सकते हैं Configuration

उपयोग जैसा के insted हैं:

context.ChangeTracker.AutoDetectChangesEnabled = false; 

//Do something here 
context.PriceRecords.Add(newPriceRecord); 

context.ChangeTracker.AutoDetectChangesEnabled = true; 
संबंधित मुद्दे