2009-06-17 14 views
9

क्या कोई भी LINQ से SQL का उपयोग कर Django's signals जैसा कुछ करने का तरीका जानता है?लिंक से एसक्यूएल में सिग्नल?

मैं नई पंक्तियों को डालने पर रिकॉर्ड करने की कोशिश कर रहा हूं और जब कुछ कॉलम अपडेट होते हैं, तो मैं वास्तव में केवल pre_save और post_save सिग्नल चाहता हूं।

मैं एक तरह से आंशिक OnFooIDChanging() और OnFooIDChanged() (जहां FooID एक प्राथमिक कुंजी है) की तरह परिभाषित का उपयोग करके कुछ मॉडलों के साथ यह करना है, लेकिन इस मॉडल जिसका प्राथमिक कुंजी के लिए काम नहीं करता है एक पहचान नहीं है, या सेट किया गया है कोड द्वारा

उन लोगों के लिए

, मैं संभवतः OnValidate() इस्तेमाल कर सकते हैं, लेकिन यह केवल pre_save होगा, और यह बाद से OnValidate()DBContext.SubmitChanges() से कहा जाता है, जो निश्चित रूप से एक दूसरे SubmitChanges() से कहा जा करने की अनुमति नहीं डेटाबेस कठिन से निपटने में आता है, भीतर, post_save मूल रूप से असंभव है जहां तक ​​मैं देख सकता हूं।

उत्तर

1

ठीक है, मैं इस पर खरगोश की मांद नीचे पूरी तरह से चले गए हैं, लेकिन मुझे लगता है कि मैं एक बहुत अच्छा समाधान है:

पहले, अपने डेटा संदर्भ के लिए एक ईवेंट हैंडलर जोड़ने के उस पोस्ट की सभी एकत्रित करेगा संकेतों को बचाएं और Dispose विधि को छुपाएं ताकि हम निपटने से पहले हम ईवेंट को सही तरीके से कॉल कर सकें। (ध्यान दें कि मैं override के बजाय new कीवर्ड का उपयोग करें। इस घटना को संभव बुला बना देता है।)

partial class MyDataContext 
{ 
    internal delegate void PostSaveHandler(); 
    internal event PostSaveHandler PostSave; 

    // This method hides the underlying Dispose because we need to call PostSave. 
    public new void Dispose(bool disposing) 
    { 
     // Obviously necessary error handling omitted for brevity's sake 
     PostSave(); 
     base.Dispose(disposing); 
    } 
} 

इसके बाद, एक T4 Template कि dbml फ़ाइल कि LINQ एसक्यूएल के लिए आपके लिए बनाए गए निरीक्षण में लिखें।

<# 
var dbml = XDocument.Load(@"MyDataContext.dbml"); 
var name = XName.Get("Type", "http://schemas.microsoft.com/linqtosql/dbml/2007"); 
var tables = from t in dbml.Descendants(name) select t.Attribute("Name").Value; 
foreach(var table in tables) 
{ 
#> 
    ... 

डेटाबेस (और इस प्रकार प्रत्येक आंशिक वर्ग) में प्रत्येक तालिका के लिए, निम्न विधियों के साथ आंशिक में जोड़ें।

public partial class Foo 
{ 
    internal void OnInsert(MyDataContext db) { 
     PreInsert(); 
     db.PostSave += delegate { PostInsert(); }; 
    } 
    internal void OnUpdate(MyDataContext db) { 
     PreUpdate(); 
     db.PostSave += delegate { PostUpdate(); }; 
    } 
    internal void OnDelete(MyDataContext db) { 
     PreDelete(); 
     db.PostSave += delegate { PostDelete(); }; 
    } 
    partial void PreInsert(); 
    partial void PostInsert(); 
    partial void PreUpdate(); 
    partial void PostUpdate(); 
    partial void PreDelete(); 
    partial void PostDelete(); 
} 

// repeat for all tables 

टी 4 के माध्यम से एक और partial MyDataContext भी जोड़ें। यह आंशिक तरीकों के लिए परिभाषाओं को जोड़ देगा जो लिंक से एसक्यूएल आपको देता है (जैसा कि मेरिट का उल्लेख है)।

public partial class MyDataContext 
{ 
    // Add these three partial methods for each table 
    partial void InsertFoo(Foo foo) 
    { 
     foo.OnInsert(this); 
     ExecuteDynamicInsert(foo); 
    } 
    partial void UpdateFoo(Foo foo) 
    { 
     foo.OnUpdate(this); 
     ExecuteDynamicUpdate(foo); 
    } 
    partial void DeleteFoo(Foo foo) 
    { 
     foo.OnDelete(this); 
     ExecuteDynamicDelete(foo); 
    } 

    // ... 
} 

उन फ़ाइलों को कहीं और सुरक्षित से छुपाएं, इसलिए कोई भी उनके साथ गड़बड़ करने की कोशिश नहीं करता है।

आपके सिग्नल ढांचे की स्थापना की गई है। अब आप अपने सिग्नल लिख सकते हैं। Foo.cs में या सभी को एक साथ एक Signals.cs फ़ाइल में या तो इन रखो:

partial class Foo 
{ 
    partial void PostInsert() 
    { 
     EventLog.AddEvent(EventType.FooInserted, this); 
    } 
} 

इसमें कुछ समय जटिल है, इसलिए यदि कुछ भी मतलब नहीं है, एक टिप्पणी छोड़ और मैं इसे संबोधित करने की मेरी पूरी कोशिश करेंगे कृपया। ओवरराइड SubmitChanges (ConflictMode failureMode):

1

मैं क्या मैं पहले से ही तैनात की तुलना में काफी आसान समाधान जो वैसे भी काम नहीं किया है

partial class MyDataContext 
{ 
    // SubmitChanges() calls this method after inserting default value for param 
    public override void SubmitChanges(ConflictMode failureMode) 
    { 

      // Pre-Submit Changes 

      //Updates    
      for (int changeCounter = 0; changeCounter < this.GetChangeSet().Updates.Count; changeCounter++) 
      {     
       var modifiedEntity = this.GetChangeSet().Updates[changeCounter];     
       // Do something, for example: 
       // var tableXEntry = new TableX() { Prop1 = "foo" }; 
       // this.tableXEntries.InsertOnSubmit(tableXEntry); 
      }    

      //Inserts    
      for (int changeCounter = 0; changeCounter < this.GetChangeSet().Inserts.Count; changeCounter++)    
      {     
       object modifiedEntity = this.GetChangeSet().Inserts[changeCounter];     
       // Do Something 
      } 


      // Submit Changes 
      base.SubmitChanges(failureMode); 


      // Post Submit Changes 

      //Updates    
      for (int changeCounter = 0; changeCounter < this.GetChangeSet().Updates.Count; changeCounter++) 
      {     
       var modifiedEntity = this.GetChangeSet().Updates[changeCounter];     
       // Do something, for example: 
       // var tableXEntry = new TableX() { Prop1 = "foo" }; 
       // this.tableXEntries.InsertOnSubmit(tableXEntry); 
      }    

      //Inserts    
      for (int changeCounter = 0; changeCounter < this.GetChangeSet().Inserts.Count; changeCounter++)    
      {     
       object modifiedEntity = this.GetChangeSet().Inserts[changeCounter];     
       // Do Something 
      } 
} 
इकाई की रूपरेखा के साथ

, तुम क्या कोशिश कर रहे हैं मैं के लिए इसी तरह कुछ करना करने के लिए: एक इकाई को सहेजने के बाद, मैं ऑडिटिंग उद्देश्यों के लिए एक अलग तालिका में एक नई प्रविष्टि डालता हूं (यह परिवर्तन से पहले इकाई की एक प्रति है)। ईएफ इकाइयों के कंटेनर (डेटा संदर्भ की तरह) पर एक SaveChanges() ईवेंट है जो परिवर्तनों को सहेजने से पहले आपको वर्तमान संदर्भ में जोड़ने की अनुमति देता है।

संबंधित मुद्दे