2011-08-25 10 views
9

एंटिटी फ्रेमवर्क कोड-फर्स्ट के साथ मुझे डेटाबेस बनाने के लिए सभी गुणों को सार्वजनिक करना होगा, इसका मतलब एंटिटी फ्रेमवर्क कोड-फर्स्ट दृष्टिकोण का उपयोग करना है, मुझे एक समृद्ध मॉडल के साथ anemic domain मिश्रित करने के लिए मजबूर होना पड़ा है? क्योंकि जिन गुणों को सार्वजनिक नहीं होना चाहिए, उन्हें होना चाहिए।एंटिटी फ्रेमवर्क कोड का उपयोग करना-पहले मुझे अपने डोमेन एनीमिक का मॉडल होना आवश्यक है?

उदाहरण के लिए:

एक अमीर मॉडल का उपयोग करना, इकाई की रूपरेखा में इस काम नहीं करेगा:

public class Car 
{ 
    private int _actualPosition; 

    public void Accelerate() 
    { 
     this._actualPosition += 10; 
    } 
} 

काम करने के लिए हम _actualPosition सार्वजनिक करने की जरूरत है:

public class Car 
{ 
    public int ActualPosition { get; set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

अब इकाई आईएमओ बदसूरत है, क्योंकि मेरे पास एक विधि है जो संपत्ति में + 10 जोड़ती है और इसे एक ही समय में सार्वजनिक करती है, मैं नहीं चाहता कि वह पीआर ऑपरेटर सार्वजनिक हो।

एक और उदाहरण:

कल्पना कीजिए मैं एक रिश्ते में कई-से-अनेक लेकिन साथ सिर्फ एक ही रास्ता की तरह हैं:

public class User 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 

    public IList<Role> Roles { get; set; } 
} 

public class Role 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 
} 

मैं एक बहुत-से-अनेक संबंध करना कैसे उस मॉडल के साथ? मेरी जानकारी के लिए वहाँ मैं एक दो-तरफा संबंध करना होगा कोई रास्ता नहीं है:

public class User 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 

    public IList<Role> Roles { get; set; } 
} 

public class Role 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 

    public IList<User> Users { get; set; } 
} 

इस मॉडल के साथ मैं बनाने के लिए सक्षम हो जाएगा कई-से-अनेक संबंध:

modelBuilder.Entity<User>() 
       .HasMany(x => x.Roles) 
       .WithMany(y => y.Users); 

मैं मैं सही हूँ यदि हां, इकाई फ्रेमवर्क मुझे प्रसन्न नहीं कर रहा है।

"एक और उदाहरण" @Slauma के जवाब के साथ काम:

modelBuilder.Entity<User>() 
      .HasMany(x => x.Roles) 
      .WithMany() 
      .Map(a => 
      { 
       a.MapLeftKey("UserId"); 
       a.MapRightKey("RoleId"); 
       a.ToTable("UserRoles"); 
      }); 
+0

आप निश्चित रूप से गुण एफई edmx में सार्वजनिक की जरूरत नहीं है, इसलिए मैं था अगर आपने पहले ईएफ कोड के लिए किया तो आश्चर्यचकित रहें। क्या वास्तव में कोई एनोटेशन या कुछ नहीं है जिसका उपयोग आप अपनी इच्छित संपत्तियों को निर्दिष्ट करने के लिए कर सकते हैं? मुझे लगता है कि आपको निश्चित रूप से एक्सेसर्स की आवश्यकता है, हालांकि। एक संरक्षित या आंतरिक एक्सेसर काम करेगा? (मैंने मूल रूप से निजी सोचा लेकिन मुझे संदेह है कि इसे कम से कम संरक्षित करने की आवश्यकता है।) – Rup

+2

@Rup: कोई टिप्पणी नहीं है। गुणों को सार्वजनिक नहीं होना चाहिए, लेकिन उन्हें ईएफ संदर्भ और मैपिंग के लिए दृश्यमान होना चाहिए। –

+0

@ Ladislav क्या आप उस मामले में ईएफ से सहमत हैं? –

उत्तर

1

लघु उत्तर: जब तक ढांचे का समर्थन करता है, तो आप इस वर्ग में बहुत ज्यादा जाम करने की कोशिश कर फंस रहे हैं यदि आप दोनों व्यवसाय नियमों और सार्वजनिक संपत्तियों के साथ प्रयास करते हैं।

लांग उत्तर: मैं एक बार बहुत ही इस तरह एक प्रणाली का इस्तेमाल किया, और मूल रूप से मैं प्रतीति है कि परीक्षण और कैप्सूलीकरण के लिए सबसे अच्छा तरीका है मेरा असली डोमेन वर्ग के साथ इस वर्ग रैप करने के लिए था के लिए आया था।

public class Car 
{ 
    private CarPersistence _carPersistence; 

    public void Accelerate() 
    { 
     this._carPersistence.ActualPosition += 10; 
    } 

    public Car (CarPersistence car) { 
     _carPersistence = car; 
    } 
} 

public class CarPersistence 
{ 
    public int ActualPosition; 
} 

जब मैं इस से पहले किया था, मैं से बात किए बिना फिर मेरे निचले स्तर हठ वर्ग एक अंतरफलक है कि मेरे परीक्षण द्वारा इस्तेमाल किया जा सकता सरल परीक्षण के लिए व्यापार वर्ग में सुई को लागू करने में सक्षम था डेटाबेस।

इस तरह की एक प्रणाली, एक "परत" पर आपके व्यवसाय वर्गों के साथ और एक अन्य "परत" पर आपके दृढ़ता वर्गों के साथ आप आसानी से एक-से-कई रिश्तों को प्राप्त कर सकते हैं, इसे आपके व्यवसाय को जो कुछ भी बनाता है हठ कक्षाओं से बाहर कक्षाएं:

public class User 
{ 
    private UserPersistence _user; 
    private IList<Persistence> _roles; 

    public User (UserPersistence user, IList<Persistence> roles) { 
     _user = user; 
     _roles = roles; 
    } 
} 

क्षमा करें, वाक्य रचना सही नहीं हो सकता है, कि सबसे अच्छा मैं यह सी # में वीबी से लिप्यंतरण याद कर सकते हैं;)

1

आप कर सकते हैं सेटअप अपने Car इकाई इस तरह:

public class Car 
{ 
    public int ActualPosition { get; private set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

यह Accelerate विधि का उपयोग करने के लिए ActualPosition संपत्ति के संशोधन को बल देता है। इस शैली का उपयोग करने का एक दुष्प्रभाव यह है कि आपकी Accelerate विधि परीक्षण योग्य नहीं है।

तुम भी इसे सेट अप इस तरह:

public class Car 
{ 
    protected int ActualPosition { get; set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

हालांकि इस दृष्टिकोण प्रतिबिंब का उपयोग किए बिना सीधे परीक्षण योग्य नहीं है।

0

हां, आपके द्वारा पोस्ट किया गया कोड Anemic Model है। इसके अलावा, मैं इसे उचित वस्तु उन्मुख कोड भी नहीं कहूंगा। बस कोई encapsulation नहीं है और वस्तुओं सिर्फ एक डेटा कंटेनर हैं। ऐसा लगता है कि आपकी पसंद का ओआरएम आपके डोमेन कार्यान्वयन विकल्पों को सीमित कर रहा है। इसके लायक होने के लिए, NHibernate आपको सीधे फ़ील्ड मैप करने की अनुमति देता है (भले ही ये फ़ील्ड केवल पढ़े जाएं)। वस्तुओं के गुणों की आवश्यकता नहीं है। उदाहरण के लिए:

<class name="Car" table="Cars" > 
    ... 
    <property name="_position" column="Position" /> 
    ... 
</class> 
+0

हां, मुझे पता है कि एनएच इसे अनुमति देता है, इसलिए मुझे हैरान है कि एंटिटी फ्रेमवर्क एक ही दावा क्यों नहीं करता है। –

3

आपका "एक और उदाहरण" सही नहीं है:

public class Car { 

    private int _position; 

    public void Accelerate() { 
     _position += 10; 
    } 
} 

के रूप में मैप किया जा सकता है। आपको अपने मॉडल वर्गों में संपत्ति के रूप में रिश्ते के दोनों सिरों का पर्दाफाश करने के लिए मजबूर नहीं किया जाता है। अपने उदाहरण में तुम इतनी तरह अपने Role वर्ग से public IList<User> Users { get; set; } को हटा सकते हैं और परिभाषित मानचित्रण:

modelBuilder.Entity<User>() 
      .HasMany(x => x.Roles) 
      .WithMany() 
      .Map(a => 
      { 
       a.MapLeftKey("UserId"); 
       a.MapRightKey("RoleId"); 
       a.ToTable("UserRoles"); 
      }); 

यह एक-से-कई रिश्तों के लिए मामला भी है। हमेशा पैरामीटर रहित With... अधिभार, WithMany(), WithRequired(), WithOptional() इत्यादि संबंधों के लिए मैपिंग को परिभाषित करने के लिए है जहां मॉडल में दोनों सिरों का खुलासा नहीं होता है।

+0

लेकिन अगर मैं इकाई फ्रेमवर्क से डेटाबेस उत्पन्न करता हूं? आपको यकीन है कि मुझे दोनों गुणों का पर्दाफाश करने की आवश्यकता नहीं होगी? –

+0

आप सही हैं, मैं परीक्षण करता हूं। धन्यवाद, मैं सवाल अपडेट कर दूंगा। –

+0

@Acaz: जब आप डीबी से मॉडल बनाते हैं तो शायद ईएफ डिफ़ॉल्ट रूप से दोनों संग्रह बना देगा। लेकिन आप जेनरेट मॉडल कक्षाओं से रिश्ते के एक तरफ हटा सकते हैं। – Slauma

1

मेरा मानना ​​है कि क्या आप के लिए देख रहे हैं निम्नलिखित है:

public class Car 
{ 
    public int Id { get; set; } 
    public int ActualPosition { get; private set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

इकाई परीक्षण के नीचे है:

[TestMethod] 
    public void AccellerateWillAddTenUnitsToTheActualPosition() 
    { 
     //Arrange 
     var car = new Car(); 
     var actualPosition = car.ActualPosition; 
     var expectedPosition = actualPosition + 10; 

     //Act 
     car.Accelerate(); 

     //Assert 
     Assert.AreEqual(car.ActualPosition, expectedPosition); 
    } 
संबंधित मुद्दे