2009-03-12 11 views
12

एक LINQ से SQL इकाई को [क्लोनिंग] डुप्लिकेट करने में सबसे अच्छा अभ्यास माना जाएगा जिसके परिणामस्वरूप डेटाबेस में एक नया रिकॉर्ड होगा?डुप्लिकेट LINQ से SQL इकाई/रिकॉर्ड?

संदर्भ यह है कि मैं एक व्यवस्थापक के ग्रिड में रिकॉर्ड के लिए डुप्लिकेट फ़ंक्शन बनाना चाहता हूं। वेबसाइट और कुछ चीजों और स्पष्ट कोशिश करने के बाद, डेटा पढ़ें, आईडी = 0 बदलें, नाम बदलें, submitChanges(), और अपवाद मारना, lol। मैंने सोचा कि मैं रुक सकता हूं और एक विशेषज्ञ से पूछ सकता हूं।

मैं रिकॉर्ड को पढ़ने के साथ शुरू करना चाहता हूं, "कॉपी ऑफ" के साथ उपसर्ग करके नाम बदलना और फिर एक नया रिकॉर्ड सहेजना चाहता हूं।

उत्तर

11

एक नया उदाहरण बनाएं और फिर सदस्य मानों की प्रतिलिपि बनाने के लिए प्रतिबिंब के साथ linq मैपिंग कक्षाओं का उपयोग करें।

उदा।

public static void CopyDataMembers(this DataContext dc, 
            object sourceEntity, 
            object targetEntity) 
{ 
    //get entity members 
    IEnumerable<MetaDataMember> dataMembers = 
     from mem in dc.Mapping.GetTable(sourceEntity.GetType()) 
           .RowType.DataMembers 
     where mem.IsAssociation == false 
     select mem; 

    //go through the list of members and compare values 
    foreach (MetaDataMember mem in dataMembers) 
    { 
     object originalValue = mem.StorageAccessor.GetBoxedValue(targetEntity); 
     object newValue = mem.StorageAccessor.GetBoxedValue(sourceEntity); 

     //check if the value has changed 
     if (newValue == null && originalValue != null 
      || newValue != null && !newValue.Equals(originalValue)) 
     { 
      //use reflection to update the target 
      System.Reflection.PropertyInfo propInfo = 
       targetEntity.GetType().GetProperty(mem.Name); 

      propInfo.SetValue(targetEntity, 
           propInfo.GetValue(sourceEntity, null), 
           null); 

      // setboxedvalue bypasses change tracking - otherwise 
      // mem.StorageAccessor.SetBoxedValue(ref targetEntity, newValue); 
      // could be used instead of reflection 
     } 
    } 
} 

... या आप DataContractSerializer का उपयोग कर इसे क्लोन कर सकते हैं:

internal static T CloneEntity<T>(T originalEntity) where T : someentitybaseclass 
{ 
    Type entityType = typeof(T); 

    DataContractSerializer ser = 
     new DataContractSerializer(entityType); 

    using (MemoryStream ms = new MemoryStream()) 
    { 
     ser.WriteObject(ms, originalEntity); 
     ms.Position = 0; 
     return (T)ser.ReadObject(ms); 
    } 
} 
+0

एक नज़र Kristofer ले कर सकते हैं। – GONeale

+0

महान जवाब! यह काम कर रहा है, मैंने प्रतिबिंब पर विचार किया था। आप इस समाधान के बारे में कैसा महसूस करते हैं? मुझे लगता है कि कोई अंतर्निर्मित क्लोन() मैं उम्मीद कर रहा था कि एक समान ऑपरेशन करेगा .. – GONeale

+1

यदि आपके पास अपनी इकाई में केवल-पढ़ने योग्य गुण हैं तो आपको यह जांचने की आवश्यकता है कि संपत्ति को propInfo.SetValue को कॉल करने से पहले एक सेटटर है या नहीं। यदि आप propInfo.GetSetMethod() एक गैर-शून्य मान देता है तो आप मेरी जांच कर सकते हैं। – pbz

3

मैं एक ही समस्या और Kristofer के कोड के साथ फंस गया था पूरी तरह से काम किया है, बहुत धन्यवाद!

यदि कोई दिलचस्पी लेता है, तो मैंने थोड़ा कोड बदल दिया ताकि लक्ष्य इकाई को पैरामीटर के रूप में स्वीकार करने के बजाय, यह एक नई वस्तु बनाता है और इसे वापस कर देता है। इसके अलावा, मैं सामान्य होने के sourceEntity पैरामीटर बना दिया है: आप गलत पर ObjectTrackingEnabled सेट के साथ DataContext से इकाई लोड तो आप के रूप में इस इकाई सम्मिलित कर सकते हैं

dataContext.MyEntities.Attach(dataContext.CloneEntity(theEntity)); 
11

:

public static T CloneEntity<T>(this DataContext dc, T sourceEntity) where T:class, new() 
{ 
    var targetEntity = new T(); 
    //... original method code... 
    return targetEntity; 
} 

तो मैं निम्न कर सकते हैं एक और DataContext

DataContext db1 = new DataContext(); 
DataContext db2 = new DataContext(); 

db2.ObjectTrackingEnabled = false; 

MyEntity entToClone = db2.Single(e => e.Id == id); 

// ... change some data if it is needed 

db1.MyEntities.InsertOnSubmit(entToClone); 
db1.SubmitChanges(); 
+0

आपको बहुत धन्यवाद, यह सबसे अच्छा समाधान है। – JanBorup

+0

हां, यह सबसे अच्छा समाधान है। धन्यवाद! – Rudy

+0

मैंने पाया कि यह बाल वस्तुओं को भी क्लोन करता है, जो कुछ मैं नहीं चाहता था। मुझे अभी भी लगता है कि यह सबसे अच्छा समाधान है। लिंक से एसक्यूएल को इसके लिए सुरुचिपूर्ण विधि में बनाया जाना चाहिए। – Rudy

0

में नए यहाँ पीटर के.एच. के रूप में वह एक ही समाधान, VB.Net में Linq करने वाली Sql Entiry क्लोन के लिए है।

Dim DC As New DataContext 
    Dim DCI As New DataContext 
    DC.ObjectTrackingEnabled = False 

     Dim RGF As sf_RuleGroup = (From G In DC.sf_RuleGroups _ 
            Where G.RuleGroupID = CInt(e.CommandArgument) _ 
            Select G).First() 
     DCI.sf_RuleGroups.InsertOnSubmit(RGF) 
     DCI.SubmitChanges() 
0

इकाई की रूपरेखा 6 में आप इस

Dim WorkoutNew As New Workout 'create a record 
ff7db.Workouts.Add(WorkoutNew) 'add it to the table (workout) 
ff7db.Entry(WorkoutNew).CurrentValues.SetValues(WorkoutsPost) ' update its values with a class with the same properties