2012-06-25 13 views
18

किसी ऐसे ग्राहक पर विचार करें जहां एक ग्राहक, कंपनी, कर्मचारी इत्यादि, एक ContactInfo संपत्ति है जिसमें बदले में पता (एस), फोन (एस), ईमेल (ओं) आदि का एक सेट होता है। , आदि ...इकाई फ्रेमवर्क केवल संग्रह पढ़ता है

यहाँ है मेरी संक्षिप्त ContactInfo:

public class ContactInfo : Entity<int> 
{ 
    public ContactInfo() 
    { 
     Addresses = new HashSet<Address>();   
    } 

    public virtual ISet<Address> Addresses { get ; private set; } 

    public Address PrimaryAddress 
    { 
     get { return Addresses.FirstOrDefault(a => a.IsPrimary); } 
    } 

    public bool AddAddress(Address address) 
    { 
     // insure there is only one primary address in collection 
     if (address.IsPrimary) 
     {     
      if (PrimaryAddress != null) 
      { 
       PrimaryAddress.IsPrimary = false; 
      } 
     } 
     else 
     { 
      // make sure the only address in collection is primary 
      if (!Addresses.Any()) 
      { 
       address.IsPrimary = true; 
      } 
     } 
     return Addresses.Add(address); 
    } 
} 

कुछ नोट (मैं 100% यकीन है कि अगर इन एफई "सर्वोत्तम प्रथाओं" कर रहे हैं नहीं कर रहा हूँ):

  • पते का संग्रह (एसएस) आभासी लोडिंग
  • के लिए आभासी है
  • संग्रह पर निजी सेटर पर प्रतिबंध लगाता है संग्रह प्रतिस्थापन
  • संग्रह का बीमा करने के संपर्क
  • प्रति कोई डुप्लिकेट पतों AddAddress पद्धति का उपयोग करके मैं बीमा कर सकते हैं हमेशा और अधिक से अधिक 1 पते जो प्राथमिक है है कि वहाँ देखते हैं कि एक ISet है ... ।

मैं चाहते हैं (यदि संभव हो) ContactInfo.Addresses.Add() विधि के माध्यम से पतों को जोड़ने को रोकने के लिए और ContactInfo.AddAddress(Address address) का उपयोग करते हुए मजबूर करने के लिए ...

मैं सेट उजागर सोच रहा हूँ ReadOnlyCollection के माध्यम से पते का क्या यह एंटिटी फ्रेमवर्क (v5) के साथ काम करेगा?

मैं इसके बारे में कैसे जाऊं?

उत्तर

3

एक तरीका है आईसीओलेक्शन संपत्ति को संरक्षित करना और आईनेमरेबल की एक नई संपत्ति बनाना है जो सिर्फ आईसीओलेक्शन संपत्ति की सूची देता है।

इसके साथ नकारात्मकता यह है कि आप ContactInfo के माध्यम से पते पर पूछने में सक्षम नहीं हैं जैसे कि इस शहर में रहने वाले सभी संपर्क जानकारी प्राप्त करें।

यह संभव नहीं है !:

from c in ContactInfos 
where c.Addresses.Contains(x => x.City == "New York") 
select c 

कोड:

public class ContactInfo : Entity<int> 
{ 
    public ContactInfo() 
    { 
     Addresses = new HashSet<Address>();   
    } 

    protected virtual ISet<Address> AddressesCollection { get ; private set; } 

    public IEnumerable<Address> Addresses { get { return AddressesCollection; }} 

    public Address PrimaryAddress 
    { 
     get { return Addresses.FirstOrDefault(a => a.IsPrimary); } 
    } 

    public bool AddAddress(Address address) 
    { 
     // insure there is only one primary address in collection 
     if (address.IsPrimary) 
     {     
      if (PrimaryAddress != null) 
      { 
       PrimaryAddress.IsPrimary = false; 
      } 
     } 
     else 
     { 
      // make sure the only address in collection is primary 
      if (!Addresses.Any()) 
      { 
       address.IsPrimary = true; 
      } 
     } 
     return Addresses.Add(address); 
    } 
} 
+0

नहीं यह एक Iset के लिए IEnumerable डाली और सभी जादू जो बाद में छिपा हुआ होना चाहिए ऐसा करना संभव हो सकता है? –

+0

@ माइकल दुर्भाग्यवश, यह मेरे लिए एक विकल्प नहीं है ... मुझे क्वेरी करने में सक्षम होना चाहिए ... – zam6ak

+1

यह पहले कोड में काम नहीं करता है। ईएफ सुरक्षित संग्रह/सेट के लिए कोई भी टेबल नहीं बनाता है। – 101V

14

एक अन्य विकल्प ईदो वैन Asseldonk ने सुझाव दिया है कि संग्रह से अपने व्यवहार को विरासत में एक कस्टम संग्रह बनाने के लिए है।

आपको आईसेट के लिए अपना स्वयं का कार्यान्वयन करना होगा लेकिन सिद्धांत समान है।

सूची को संशोधित करने और उन्हें अप्रचलित के रूप में चिह्नित करने वाली किसी भी विधि को छिपाने से आप प्रभावी रूप से एक ReadOnlyCollection प्राप्त करते हैं लेकिन EF संग्रह के रूप में अनबॉक्स किए जाने पर भी इसे संशोधित करने में सक्षम होगा।

:

var list = ListProperty.ToList(); 
list.Add(entity) 
ListProperty = list; 

कहाँ

public virtual EntityCollection<MyEntity> ListProperty { get; protected set; } 

और यहाँ EntityCollection है: इसलिए हम जब आइटम जोड़ने संग्रह Unbox की जरूरत नहीं है मेरे संस्करण में मैं सूची के लिए एक अंतर्निहित ऑपरेटर रूपांतरण जोड़ दिया है

public class EntityCollection<T> : Collection<T> 
{ 
    [Obsolete("Unboxing this collection is only allowed in the declarating class.", true)] 
    public new void Add(T item) { } 

    [Obsolete("Unboxing this collection is only allowed in the declarating class.", true)] 
    public new void Clear() { } 

    [Obsolete("Unboxing this collection is only allowed in the declarating class.", true)] 
    public new void Insert(int index, T item) { } 

    [Obsolete("Unboxing this collection is only allowed in the declarating class.", true)] 
    public new void Remove(T item) { } 

    [Obsolete("Unboxing this collection is only allowed in the declarating class.", true)] 
    public new void RemoveAt(int index) { } 

    public static implicit operator EntityCollection<T>(List<T> source) 
    { 
     var target = new EntityCollection<T>(); 
     foreach (var item in source) 
      ((Collection<T>) target).Add(item); // unbox 

     return target; 
    } 
} 

इस तरह आप अभी भी अपने लिंक को सामान्य रूप से चला सकते हैं लेकिन संग्रह संपत्ति को संशोधित करने का प्रयास करते समय उपयोग की उचित चेतावनी प्राप्त होगी। यह एक संग्रह करने के लिए संयुक्त राष्ट्र के मुक्केबाजी एक ही रास्ता होगा:

((Collection<MyEntity>)ListProperty).Add(entity); 
संबंधित मुद्दे