2009-03-31 24 views
31

मैं इकाई की रूपरेखा का उपयोग कर रहा हूँ और मैं "फिर से खोज" वस्तुओं मैं अभी बनाया के साथ एक समस्या हो रही करने के लिए जोड़ा वस्तुओं ... मूल रूप से यह इस प्रकार है:इकाई की रूपरेखा: पुनः पाने के हाल ही में संदर्भ

string theId = "someId"; 

private void Test() 
{ 
    using(MyEntities entities = new MyEntities()) 
    { 
    EntityObject o = new EntityObject(); 
    o.Id = theId; 
    entities.AddToEntityObject(o); 
    CallSomeOtherMethod(entities); 
    } 
} 

void CallSomeOtherMethod(MyEntities ents) 
{ 
    EntityObject search = ents.EntityObject.FirstOrDefault(o => o.Id == theId); 
    if(search == null) 
    { 
    Console.WriteLine("wha happened???"); 
    } 
} 

(कोई गारंटी नहीं कोड btw काम करता है - यह सब मेरे सिर से है)

क्यों नहीं क्वेरी "लगता है" करता EntityObject कि सिर्फ बनाया गया था?

अगर मैं AddToEntityObject के बाद SaveChanges() को कॉल करता हूं तो यह काम करता है (जो मुझे आश्चर्य नहीं करता) लेकिन यह कैश से ठीक से क्यों नहीं खींचता है?

मैं अभी भी इस सामान पर हरे रंग की कर रहा हूँ तो मैं आशा करती हूं कि कुछ वास्तव में आसान बात यह है कि मैं सिर्फ अनदेखी कर रहा हूँ यह है कि ...

धन्यवाद

उत्तर

18

इसका कारण यह है ents.EntityObject.WhatEver होता है हमेशा डेटा स्रोत से पूछताछ करता है। यह एक डिजाइन निर्णय है। वे इसे इस तरह से करते हैं, क्योंकि अन्यथा उन्हें स्थानीय कैश के खिलाफ डेटासोर्स के खिलाफ क्वेरी निष्पादित करना होगा और फिर परिणामों को मर्ज करना होगा। जैसा कि डेवलपर्स में से एक ने ब्लॉग में बताया है (बिल्कुल याद नहीं किया जा सकता है) वे लगातार इसे संभालने में असमर्थ थे।

जैसा कि आप कल्पना कर सकते हैं कि किनारे के किनारे बहुत अच्छे हैं जिन्हें आपको सही तरीके से संभालना है। आप डेटाबेस में किसी और द्वारा बनाई गई स्थानीय रूप से बनाई गई एक आईडी पा सकते हैं। यह आपको हर प्रश्न पर (लगभग) संघर्षों को संभालने के लिए तैयार होने के लिए मजबूर करेगा। हो सकता है कि वे डेटा कैश से पूछताछ करने के लिए स्थानीय कैश और विधियों से पूछताछ करने के तरीके बना सकते थे, लेकिन यह भी स्मार्ट नहीं है।

आप Transparent Lazy Loading for Entity Framework पर एक नज़र डाल सकते हैं। यह सामान्य कोड जनरेटर को प्रतिस्थापित करता है और आप उन संस्थाओं को प्राप्त करते हैं जो उनके संबंधित इकाई संग्रह और इकाई संदर्भों को स्वचालित रूप से एक्सेस पर पॉप्युलेट करते हैं। यह सभी

if (!Entity.ReleatedEntities.IsLoaded) 
{ 
    Entity.RelatedEntities.Load(); 
} 

कोड टुकड़े से बचाता है। और आप संग्रहों से पूछ सकते हैं क्योंकि वे हमेशा निहित रूप से लोड होते हैं। लेकिन यह समाधान भी सही नहीं है। कुछ मुद्दे हैं। उदाहरण के लिए, यदि आप एक नई इकाई बनाते हैं और संबंधित इकाइयों के संग्रह तक पहुंचते हैं, तो आपको अपवाद मिलेगा क्योंकि कोड डेटाबेस से संबंधित इकाइयों को पुनर्प्राप्त करने में असमर्थ है। डेटा बाध्यकारी से संबंधित एक मुद्दा भी है और कुछ और हो सकता है मुझे पता नहीं है।

अच्छी बात यह है कि आपको स्रोत कोड मिलता है और आप स्वयं को समस्याओं को ठीक करने में सक्षम होते हैं और यदि मुझे कुछ समय लगता है तो मैं पहले मुद्दे की जांच करने जा रहा हूं। लेकिन मुझे पूरा यकीन है कि यह ठीक करना आसान नहीं होगा, क्योंकि मुझे उम्मीद है कि कुछ मामला डेटाबेस को मार नहीं रहा है अगर इकाई अभी बनाई गई है तो अपेक्षित व्यवहार नहीं है।

+0

टिप/अपडेट के लिए धन्यवाद ... मैं इस प्रश्न को थोड़ी देर के लिए खोलने जा रहा हूं उम्मीद है कि कोई मुझे अधिक जानकारी दे सकता है ... लेकिन धन्यवाद – dovholuk

1

आपके पास कई विकल्प हैं। हाल ही में जोड़ा गया जानकारी पुनर्प्राप्त करने के लिए आप अपना स्वयं का तंत्र बनाने के लिए ObjectContext को अन्य आंशिक कक्षा के साथ बढ़ा सकते हैं।

या आप सिर्फ इतना है कि ObjectContext.ObjectStateManager के माध्यम से लग रहा है 'जोड़ा' ObjectStateEntries की तलाश में है, और फिर आप के लिए क्या देख रहे लगाने के लिए वस्तुओं के लिए LINQ का उपयोग ObjectContext पर एक विस्तार विधि डाल सकता है।

2

मैंने हाल ही में इसी प्रश्न के साथ संघर्ष किया है। प्रश्न पूछने के 2 साल बाद मैं इस जवाब को पोस्ट कर रहा हूं कि उम्मीद है कि कोड का यह बिट किसी को जवाब खोजने में मदद कर सकता है।

मैंने मूल रूप से एक विस्तार विधि (जैसा कि एलेक्स जेम्स द्वारा सुझाया गया है) को "खोज" कहा जाता है जिसे "कहां" करता है, उसी तरह संचालित होता है, लेकिन "ढूंढें" ऑब्जेक्ट कॉन्टेक्स्ट को यह भी देखने के लिए जांचता है कि कोई जोड़ा गया इकाई है या नहीं जो दिए गए भविष्य को संतुष्ट करता है। यह आपको एक इकाई खोजने की अनुमति देता है भले ही इसे अभी तक डेटाबेस में सहेजा नहीं गया है।

रिटर्न एक IQueryable (टी का) खोजें ताकि आप इसे किसी भी अन्य LINQ ऑपरेटर की तरह उपयोग कर सकें।

<Extension()> 
Public Function Find(Of T As Class)(ByVal OSet As ObjectSet(Of T), _ 
     ByVal predicate As Expression(Of Func(Of T, Boolean))) _ 
     As System.Linq.IQueryable(Of T) 

    'Check the object context for Added objects first. 
    Dim AddedContextObjects = OSet.Context.ObjectStateManager _ 
         .GetObjectStateEntries(EntityState.Added) _ 
         .Select(Function(entity) entity.Entity).OfType(Of T)() 


    Dim Cpredicate = predicate.Compile 
    Dim MatchingObjects As New List(Of T) 

    For Each TObj As T In AddedContextObjects 
     If Cpredicate.Invoke(TObj) Then 
      MatchingObjects.Add(TObj) 
     End If 
    Next 

    'Now include a query to retrieve objects from the DB. 
    Dim DBObjects = OSet.Where(predicate) 

    If MatchingObjects.Count > 0 Then 
     'We found some added objects in the context. 
     'We want to return these objects as well as any Objects in DB 
     'that satisfy the predicate. 
     Return MatchingObjects.Union(DBObjects).AsQueryable 
    Else 
     'We didn't find any added objects in the context, 
     'so we just return the DB query. 
     Return DBObjects 
    End If 

End Function 
17

मैं एक ही स्थिति में था। मैं इस विस्तार विधि है कि कम से कम मेरे लिए समस्या का हल (मैं अपने संदर्भ में यानी संघर्ष के साथ मुद्दों की जरूरत नहीं है ...)

public static IEnumerable<T> WhereInclAdded<T>(this ObjectSet<T> set, Expression<Func<T, bool>> predicate) where T : class 
    { 
     var dbResult = set.Where(predicate); 

     var offlineResult = set.Context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).Select(entry => entry.Entity).OfType<T>().Where(predicate.Compile()); 

     return offlineResult.Union(dbResult); 
    } 
+4

डीबीएसईटी के लिए मैंने इसे बदल दिया: var OfflineResult = set.Local.Where (predicate.Compile()); – John

+0

जहांइनक्लेड के बजाय, स्वच्छ और सुंदर विचार, मैंने जहां कहीं भी जोड़ा था ... चीयर्स – Monah

+2

नोट यहां एक सूक्ष्म विवरण है:। जहां IQueryable का उपयोग किया जा रहा है, जबकि स्थानीय IENumerable का उपयोग कर रहा है। यदि आप पहले उपयोग करते हैं। (अभिव्यक्ति.कंपाइल()) पहले में यह IENumerable एक को कॉल करेगा, जिससे पूरे टेबल को स्मृति में लोड किया जा सकेगा। अगर आप इस कोड का आधार अपने आप के आधार पर उपयोग कर रहे हैं तो बस एक विवरण। –

17

नए जोड़े वस्तु स्थानीय डेटा स्रोत में है के रूप में यह कायम नहीं कर रहा है लिखा था डेटाबेस अभी तक तो आप कह सकते हैं EntityObject search = ents.EntityObject.FirstOrDefault(o => o.Id == theId) ?? ents.EntityObject.Local.FirstOrDefault(o => o.Id == theId);

+0

वाह इस धन्यवाद की तलाश में था! – CMS

+0

धन्यवाद ... अच्छा समाधान – jstuardo

3

विस्तार विधि bellow <>

public static T TryAttach<T>(this DbSet<T> dbSet, T entity, Expression<Func<T, bool>> predicate) where T : class 
{ 
    T found = dbSet.Local.SingleOrDefault(predicate.Compile()); 
    if (found == null) dbSet.Attach(entity); 
    return found ?? entity; 
} 

DbSet कैसे उपयोग करने के लिए है:

contextInstance.MyEntity.TryAttach(entityInstance, e => e.ID == entityInstance.ID); 

बीटीडब्ल्यू: मुझे जेनेरिक पसंद है!

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