2014-10-08 2 views
7

मैं एंटिटी फ्रेमवर्क 6 का उपयोग कर रहा हूं और मुझे किसी इकाई के गुणों को अपडेट करने की आवश्यकता है।ईएफ में एंटिटी प्रॉपर्टी अपडेट करें जहां संपत्ति एक और इकाई है

मैं निम्नलिखित संस्थाओं है

_repository.Update<File>(file, x => x.Data, x => x.Mime, x => x.Updated); 

भंडार विधि पीछा कर रहा है:

public void Update<T>(T entity, 
         params Expression<Func<T, Object>>[] properties) 
         where T : class 
{ 

    _context.Set<T>().Attach(entity); 

    foreach (var property in properties) 
    { 
    MemberExpression expression = 
        property.Body is MemberExpression ? 
        (MemberExpression)property.Body : 
        (MemberExpression)(((UnaryExpression)property.Body) 
                    .Operand); 
    _context.Entry<T>(entity) 
      .Property(expression.Member.Name).IsModified = true; 
    } 
} 

यह Data और के लिए ठीक काम करता है

public class File 
{ 
    public Int32 Id { get; set; } 
    public Byte Data { get; set; } 
    public DateTime Updated { get; set; } 
    public virtual Mime Mime { get; set; } 
} 
public class Mime 
{ 
    public Int32 Id { get; set; } 
    public String Name { get; set; } 
    public virtual ICollection<File> Files { get; set; } 
} 

तो मैं निम्नलिखित इस्तेमाल किया अद्यतन गुण लेकिन Mime के लिए नहीं। मुझे त्रुटि मिलती है:

The property 'Mime' on type 'File' is not a primitive or complex property. The Property method can only be used with primitive or complex properties. Use the Reference or Collection method.

क्या यह काम करना संभव है और इसे मेरे भंडार विधि पर एकीकृत करना संभव है?

+5

पहला सवाल यह है: आपके पास यह विस्तृत 'अपडेट' विधि क्यों है? संशोधित गुणों को चिह्नित करने के लिए आप इसे ईएफ के परिवर्तन ट्रैकर पर क्यों नहीं छोड़ सकते? बड़ी तस्वीर क्या है? –

+0

फ़ाइल इकाई में एक संपत्ति डेटा है जो कि बहुत बड़ा हो सकता है क्योंकि इसमें फ़ाइल है ... इसलिए मैं डेटा को स्मृति में लोड किए बिना कुछ फ़ील्ड अपडेट करना चाहता हूं। इसका कोई मतलब भी है क्या? यह तब काम करता था जब मेरे पास उससे संबंधित संस्थाएं नहीं होतीं। –

+0

आपको * टेबल विभाजन * पर एक नज़र रखना चाहिए। –

उत्तर

0

हाँ, मुझे लगता है कि किया जा सकता है। यहां समस्या यह है कि जब भी कोई संपत्ति तालिका का हिस्सा होती है, या यह नौसैनिक संपत्ति है, तो मुझे जांचने का कोई आसान तरीका नहीं दिखाई देता है। इस प्रकार सही व्यवहार को कॉल करना मुश्किल है।

यदि आप रुचि रखते हैं, तो EF6 स्रोत कोड, InternalEntityEntry.cs ->Property(..) पर एक नज़र डालें जो मेटाडेटा के माध्यम से बड़ी मात्रा में संपत्ति सत्यापन करता है।

मुख्य विचार मूल रूप से अपने वैचारिक मॉडल को स्कैन करना है, और यह निर्धारित करना है कि जब भी संपत्ति नौसैनिक संपत्ति है (उदाहरण के लिए यदि संपत्ति किसी अन्य तालिका की ओर जाता है), या यदि यह जटिल/आदिम है।

इसके अनुसार, आप सही कार्यक्षमता को कॉल करते हैं।

var propertyName = expression.Member.Name;            
var propertyType = __get_property_type__(propertyName); 

if(propertyType==Property || propertyType==Complex) 
{ 
    _context.Entry<T>(entity) 
     .Property(propertyName).IsModified = true; 

    continue; 
} 

if(propertyType==Navigational){ 

    // hm, do we need Attach it first?! 
    // not sure.. have to test first. 
    dynamic underlyingReference = entity.GetType() 
      .GetProperty(propertyName) 
      .GetValue(entity, null); 

    _context.Entry(underlyingReference).State = EntityState.Modified; 
} 

यहां पकड़ __get_property_type__ है जो काम करता है। Microsoft.Data.Edm.dll है कि आप वैचारिक मॉडल के साथ काम करते हैं, लेकिन यह इतना आसान नहीं है कि मुझे लगता है।

इस तरह कैसे EF6 का पता लगाता है कि अगर हम संदर्भ संपत्ति या नहीं के साथ काम कर रहे हैं:

EdmMember member; 
EdmEntityType.Members.TryGetValue(propertyName, false, out member); 

var asNavProperty = member as NavigationProperty; 
// if asNavProperty!=null, we have navigation property. 
-2

100% Gerts बिंदु। मुझे आपके पास जिस तरह से समस्या है, उससे संपर्क करने का कोई कारण नहीं है। वैसे भी, प्रश्न का उत्तर देने के लिए। आपके पास एक और जवाब है। संभावित रूप से उपयोगी।

क्या याद आ रही है:

कैसे संदर्भ से प्रबंधित प्रकार की एक सूची प्राप्त करने के लिए।

public static IList<Type> GetContextManagedTypes(DbContext context) { 
     ObjectContext objContext = ((IObjectContextAdapter)context).ObjectContext; 
     MetadataWorkspace workspace = objContext.MetadataWorkspace; 
     IEnumerable<EntityType> managedTypes = workspace.GetItems<EntityType>(DataSpace.OSpace); 

     var typeList = new List<Type>(); 
     foreach (var managedType in managedTypes) { 
      var pocoType = managedType.FullName.GetCoreType(); 
      typeList.Add(pocoType); 
     } 

     return typeList; 
    } 
संबंधित मुद्दे