मेरे पास एक डेटाग्रिड है जिसके पास एक बाइंडिंगसोर्स के माध्यम से एक संग्रह है:

            bsProducts.DataSource = cc.Products.Local.ToBindingList();

ग्रिड में किसी एक संस्था को एक अलग रूप में संपादित (और बचाया) जा रहा है और मैं इस फॉर्म पर ग्रिड को रिफ्रेश करना चाहूंगा, अब मैंने इकाई को फिर से लोड करने की कोशिश की, पूरे स्थानीय संदर्भ को फिर से लोड किया, लेकिन किसी कारण से यह नहीं है संबंधित उप संस्थाओं को पढ़ना। अब जब मैं पूरे फॉर्म को बंद कर देता हूं और फिर से खोल देता हूं तो सब पढ़ा जा रहा है।

निम्नलिखित कोड का उपयोग करके इकाई को ताज़ा करने के लिए:

        await cc.Entry<Product>(product).ReloadAsync();

लेकिन यह किसी भी संबंधित संस्थाओं को लोड नहीं करेगा जो उत्पाद इकाई के लिए बाध्य हैं। मैं बाद में बाइंडिंग स्रोत को अपडेट करने के लिए पीछे हट गया लेकिन कोई भाग्य नहीं।

7
Martin 24 नवम्बर 2015, 15:15

2 जवाब

सबसे बढ़िया उत्तर

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

इस विधि का उपयोग करके आप बस कॉल कर सकते हैं ...

cc.Visit(product, e => cc.Entry(e).Reload());

... और आप देखेंगे कि product और सभी पालन वाली वस्तुओं को पुनः लोड किया गया है।

यहाँ कोड है:

public static class DbContextExtensions
{
    public static void Visit(this DbContext context, object entity, Action<object> action)
    {
        Action<object, DbContext, HashSet<object>, Action<object>> visitFunction = null; // Initialize first to enable recursive call.
        visitFunction = (ent, contxt, hashset, act) =>
          {
              if (ent != null && !hashset.Contains(ent))
              {
                  hashset.Add(ent);
                  act(ent);
                  var entry = contxt.Entry(ent);
                  if (entry != null)
                  {
                      foreach (var np in contxt.GetNavigationProperies(ent.GetType()))
                      {
                          if (np.ToEndMember.RelationshipMultiplicity < RelationshipMultiplicity.Many)
                          {
                              var reference = entry.Reference(np.Name);
                              if (reference.IsLoaded)
                              {
                                  visitFunction(reference.CurrentValue, contxt, hashset, action);
                              }
                          }
                          else
                          {
                              var collection = entry.Collection(np.Name);
                              if (collection.IsLoaded)
                              {
                                  var sequence = collection.CurrentValue as IEnumerable;
                                  if (sequence != null)
                                  {
                                      foreach (var child in sequence)
                                      {
                                          visitFunction(child, contxt, hashset, action);
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
          };
        visitFunction(entity, context, new HashSet<object>(), action);
    }

    // Get navigation properties of an entity type.
    public static IEnumerable<NavigationProperty> GetNavigationProperies(this DbContext context, Type type)
    {
        var oc = ((IObjectContextAdapter)context).ObjectContext;
        var objectType = ObjectContext.GetObjectType(type); // Works with proxies and original types.

        var entityType = oc.MetadataWorkspace.GetItems(DataSpace.OSpace).OfType<EntityType>()
                           .FirstOrDefault(et => et.Name == objectType .Name);
        return entityType != null
            ? entityType.NavigationProperties
            : Enumerable.Empty<NavigationProperty>();
    }
}

यह एक पुनरावर्ती कार्य है जिसे विस्तार विधि में लपेटा गया है। मैंने पुनरावर्ती भाग को लपेटा ताकि मैं स्थानीय HashSet ग्राफ को भेज सकूं, जो संस्थाओं का दौरा करता है और इस तरह परिपत्र संदर्भों को रोकता है। मूल रूप से फ़ंक्शन इकाई के लिए निर्दिष्ट कार्रवाई को लागू करता है, फिर अपने नेविगेशन गुणों को ढूंढता है - जो संदर्भ या संग्रह हो सकते हैं - अपने मूल्यों (CurrentValue) प्राप्त करता है और फिर इन मूल्यों के लिए खुद को कॉल करता है।

ध्यान दें कि मैं यह भी जांचता हूं कि क्या नेविगेशन गुण लोड किए गए हैं। इसके बिना, आलसी लोडिंग की एक अंतहीन श्रृंखला शुरू हो सकती है।

यह भी ध्यान दें कि यह ग्राफ में प्रत्येक इकाई के लिए एक क्वेरी फायर करता है। यह बड़े ऑब्जेक्ट ग्राफ के लिए एक उपयुक्त विधि नहीं है। यदि आप बड़ी मात्रा में डेटा ताज़ा करना चाहते हैं, तो आपको एक अलग दृष्टिकोण लेना चाहिए, अधिमानतः एक नया संदर्भ बनाना चाहिए।

2
Gert Arnold 29 नवम्बर 2015, 13:43

क्या आपने ApplyCurrentValues () फ़ंक्शन की कोशिश की है, यह आपके संदर्भ की तरह दिखता है, यदि आप पहले से ही एक ताज़ा फ़ंक्शन बनाते हैं, तो आप नए मान नहीं ले रहे हैं:

 bsProducts.DataSource = cc.Products.Local.ToBindingList();
 bsProducts.DataBind();

तब आप ऐसा करने से पहले वर्तमान मूल्यों को लागू करना चाह सकते हैं।

क्षमा करें यदि यह इसे हल नहीं करता है, तो मुझे एक समान समस्या थी और इसे इसके साथ हल किया, हो सकता है कि आपका मामला न हो।

https://msdn.microsoft.com/en-us/library/dd487246(v=vs.110).aspx

2
Antoine Pelletier 24 नवम्बर 2015, 15:39