मैं एक इकाई वस्तु ग्राफ के लिए एक "आगंतुक" पर काम हुआ। अपने प्रश्न को देखते हुए मैंने इसे आपके मामले में उपयोगी बनाने के लिए आखिरी स्पर्श दिया (और कई अन्य)। यह जाने-माने विज़िटर पैटर्न में वास्तविक विज़िटर नहीं है, लेकिन यह मूल रूप से वही बात करता है: यह ऑब्जेक्ट ग्राफ़ को घुमाता है और प्रत्येक इकाई के लिए कुछ क्रियाएं निष्पादित करता है।
इस विधि आप बस फोन कर सकते हैं का उपयोग करना ...
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
) प्राप्त होते हैं और फिर इन मानों के लिए स्वयं को कॉल करते हैं।
ध्यान दें कि मैं यह भी जांचता हूं कि नेविगेशन गुण लोड किए गए हैं या नहीं। इसके बिना, आलसी लोडिंग की एक अंतहीन श्रृंखला ट्रिगर हो सकती है।
यह भी ध्यान दें कि यह ग्राफ में प्रत्येक इकाई के लिए एक क्वेरी को आग लगा देता है। यह बड़े ऑब्जेक्ट ग्राफ़ के लिए उपयुक्त विधि नहीं है। यदि आप बड़ी मात्रा में डेटा रीफ्रेश करना चाहते हैं तो आपको एक अलग दृष्टिकोण लेना चाहिए, अधिमानतः एक नया संदर्भ बनाएं।
पुनः लोड करने के बाद, क्या आप फिर से बांधते हैं? – MichaelMao
हां, लेकिन ReloadAsync के बाद संपत्ति में अभी भी संबंधित संबंधित संबंधित संस्थाओं में से कोई भी नहीं है, केवल पुराने हैं। मैंने मैन्युअल रूप से संबंधित इकाइयों को लोड करके और उन्हें सूची <> के रूप में असाइन करके एक समाधान किया है। – Martin
अद्यतन –