2012-11-07 7 views
8

एक नई परियोजना के लिए डेटा एक्सेस लेयर बनाने की कोशिश करते समय, मैं केवल ओओपी/डिजाइन/जेनेरिक समस्या (डेटाबेस तक पहुंचने के लिए ईएफ 4.3 का उपयोग करके) के रूप में कल्पना कर सकता हूं।मेरी सेवा परत पर एंटीटी फ्रेमवर्क को संदर्भित करने की आवश्यकता से कैसे बचें?

  • अलग संदर्भ वस्तुओं मैं अपने प्रोजेक्ट में एक ही कनेक्शन स्ट्रिंग साझा करना चाहिए पर है:

    मुख्य रूप से मैं इस डेटा परत के साथ दो चीजें हासिल करना चाहता था।

  • सामान्य कार्यान्वयन के साथ सार भंडार वर्ग।

किसी कारण से, मैं सेवा परत पर EntityFramework को संदर्भित किए बिना अपना समाधान संकलित नहीं कर सकता। जो मैं खोज रहा हूं वह इसे ठीक करने का एक तरीका है। यहां मेरे पास है:

//Project/Namespace BusinessLogicLayer.DomainClasses 
//POCO classes mapped on Entity Framework. 

//Project/Namespace DataAccessLayer.Base 
//Base classes and interfaces for all data access layer, such as: 

public abstract class BaseContext<TContext> : DbContext where TContext : DbContext 
{ 
    //To allow multiple contexts sharing the same connection string 
    protected BaseContext(): base("name=MyConnectionString") {} 
} 

//Generic interface for a read-only repository 
public interface IReadOnlyRepository<T> : IDisposable where T : class 

//Generic interface for a read/write repository 
public interface IRepository<T> : IReadOnlyRepository<T> where T : class 

//Basic implementation for a read-only repository 
public abstract class BaseReadOnlyRepository<C, T> : IReadOnlyRepository<T> 
    where T : class 
    where C : BaseContext<C>, new() 
{ 
} 

//Basic implementation for a read/write repository 
public abstract class BaseRepository<C, T> : IRepository<T> 
    where T : class 
    where C : BaseContext<C>, new() 
{ 
} 

//Project DataAccessLayer.AccountContext/ Namespace DataAccessLayer 
//Context class: 

public class AccountContext : BaseContext<AccountContext> {} 

//With this, I can have simple repositories: 

public class UserRepository : BaseRepository<AccountContext, User> 
{ //All implementation comes from the base abstract class, unless I need to change it (override methods) 
} 

मेरे पास डेटा एक्सेस और एप्लिकेशन (विंडोज फॉर्म) के बीच एक सेवा परत है। क्योंकि मेरे पास एक सामान्य भंडार है, यह सामान्य सेवाओं के लिए एक अच्छा और तर्क विचार लग रहा था। अंत में, बहुत भंडार संरचना के समान में:

//Project/Namespace BusinessLogicLayer.Services 
//Service layer supposed to reference only the repository project and not Entity Framework. 

//Generic interface for a read-only service working with a read-only repository 
public interface IReadOnlyService<T> where T : class {} 

//Generic interface for a read/write service working with a read/write repository 
public interface IService<T> : IReadOnlyService<T> where T : class 

//Base implementation for a read-only service 
public abstract class BaseReadOnlyService<T, R> : IReadOnlyService<T> 
    where T : class 
    where R : IReadOnlyRepository<T>, new() 
{ 
} 

//Base implementation for a read/write service 
public abstract class BaseService<T, R> : IService<T> 
    where T : class 
    where R : IRepository<T>, new() 
{ 
} 

//Concrete sample service 
public class UserService : BaseService<User, UserRepository> 
{ //As with the repository I can change the default behavior of implementation overriding methods 
} 

इस स्थापना के साथ, संकलित करने के लिए एक ही रास्ता सेवा परत परियोजना पर इकाई की रूपरेखा के संदर्भ के लिए है। मैं एंटिटी फ्रेमवर्क को संदर्भित करने की आवश्यकता से कैसे बच सकता हूं?

इस बिंदु पर, मैं इसे सब कुछ बाहर फेंकने और सब कुछ पुनर्निर्माण करने के लिए तैयार हूं, लेकिन यह एकमात्र तरीका है जिसे मैंने अपनी जरूरतों को पूरा करने के लिए पाया है (डीबीकॉन्टेक्स्ट शेयरिंग कनेक्शन स्ट्रिंग्स, जेनेरिक रिपोजिटरी कोड के प्रतिकृति से बचने के लिए) ।

किसी भी मदद की सराहना करें। धन्यवाद।

--Edit - यहाँ कुछ अतिरिक्त कदम मैं 3 घंटे के बाद मैं question--

आदेश में इस यह पता लगाने के लिए तैनात किया था सहित, मैं ऊपर एक ही कोड के साथ एक नमूना प्रोजेक्ट बनाने के लिए शुरू कर दिया साथ ही मूल परियोजना पर जितना संभव हो सके परिणामों की नकल करने के लिए कुछ कार्यान्वयन।

मैंने डोमेन क्लास प्रोजेक्ट, संपूर्ण बेस डेटा लेयर प्रोजेक्ट और फिर संदर्भ प्रोजेक्ट बनाया है। मैंने देखा कि मुझे संदर्भ परियोजना पर एंटीटी फ्रेमवर्क का संदर्भ देने की आवश्यकता है, भले ही संदर्भ वर्ग सीधे डीबीकॉन्टेक्स्ट से प्राप्त न हो। इसके बजाय, यह एक सार वर्ग से निकला है जो डीबीकॉन्टेक्स्ट से निकला है। यह ठीक है हालांकि मेरे संदर्भ में डीबीसेट्स और डीबीकॉन्टेक्स्ट से संबंधित कोई अन्य कार्यान्वयन होगा।

अगला रिपोजिटरी प्रोजेक्ट है। अन्य सभी तीन (डोमेन, बेस डेटा परत और संदर्भ) को संदर्भित करने की आवश्यकता है। मेरे भंडार में कोई कोड नहीं है। सभी funcionality पूर्वजों पर निहित है। मैं रिपोजिटरी प्रोजेक्ट को संकलित करने का प्रयास करता हूं और वीएस को मुझे एंटीटी फ्रेमवर्क को संदर्भित करने की आवश्यकता होती है। मुझे आश्चर्य है कि यह वास्तव में पुस्तकालयों को एम्बेड करने का मामला है। अगर इसकी पुष्टि हुई है, तो यह आश्चर्यचकित होगा। अन्य परियोजनाओं के उत्पादन पर इकाई फ्रेमवर्क लाइब्रेरी मौजूद है। मुझे इसे यहां संदर्भित करने की आवश्यकता क्यों होगी? वीएस को क्या बना रहा है इसकी आवश्यकता है?

वैसे भी, परीक्षण उद्देश्यों के लिए, मैंने संदर्भ जोड़ा। आखिरकार, मैं डेटा परत के अंदर हूं। में इसके साथ जी सकता हूँ। सेवा परत पर आगे बढ़ना। सादगी के लिए, मैंने सभी सेवा कक्षाओं को एक ही परियोजना में रखा है।

एक संभावित दोष यह है कि सेवा सार कक्षाओं के लिए बाधाओं में से एक भंडार इंटरफ़ेस है।इसके लिए मुझे अपनी सेवा परत पर बेस डेटा परत का संदर्भ जोड़ने की आवश्यकता है। शायद पहले से ही ऐसा कुछ है जो मैं कर सकता हूं जो मुझे केवल भंडार संदर्भ का उपयोग करने की अनुमति देता है। मेरे पास आधार डेटा परत का संदर्भ देने के अलावा कोई विकल्प नहीं है।

आखिरकार, मेरी ठोस सेवा बनाई गई है और वीएस मुझे निम्न त्रुटि संदेश देता है: 'System.Data.Entity.DbContext' प्रकार को उस असेंबली में परिभाषित किया गया है जिसका संदर्भ नहीं दिया गया है। आपको असेंबली 'EntityFramework, संस्करण = 4.3.1.0, संस्कृति = तटस्थ, PublicKeyToken = b77a5c561934e089' का संदर्भ जोड़ना होगा।

तो अंत में, चलने का एकमात्र तरीका सेवा परत पर इकाई फ्रेमवर्क का संदर्भ देना है। और कुछ बिंदु पर, जब विंडोज फॉर्म ऐप का निर्माण होता है, तो मुझे एंटिटी फ्रेमवर्क का भी संदर्भ देना होगा।

इन संदर्भों से बचने के लिए मुझे क्या करना चाहिए? इस ढांचे पर मेरे पास क्या सुधार हो सकते हैं?

मुझे क्या पता है कि मेरे ऐप को निश्चित रूप से यह नहीं पता है कि इकाई फ्रेमवर्क अन्य परतों पर कहीं भी शामिल है। सेवा परत भी नहीं है। सेवाएं केवल भंडार का उपभोग करेंगी। रेपॉजिटरीज परीक्षण के लिए फर्जी डेटा भी प्रदान कर सकते हैं।

यदि कोई दिलचस्पी लेता है, तो मैंने इसे लिखते समय बनाई गई परियोजना को अपलोड किया। यह एक 1,17 एमबी ज़िप फ़ाइल है जिसमें कोई भी बाइनरी नहीं है (एंटीटी फ्रेमवर्क 4.3.1 डीएल को छोड़कर जो मुझे Nuget के माध्यम से मिला)। लिंक: http://www.mediafire.com/?b45zkedy2j7eocc

फिर से, मदद के लिए धन्यवाद।

+0

एक मूर्ख सवाल की तरह लगता है लेकिन मुझे यह सुनिश्चित करने की आवश्यकता महसूस होती है: क्या डेटा एक्सेस परत सेवा परत के साथ संकलित है क्योंकि यह अभी खड़ा है? – tmesser

+0

हम ... बिल्कुल मूर्ख नहीं। वास्तव में मुझे लगता है कि आपने मुझे सही दिशा में रखा होगा। आपकी टिप्पणी पढ़ने के बाद मैंने समस्या का प्रदर्शन करने वाली एक नमूना परियोजना बनाई। मैंने उपरोक्त मूल प्रश्न के बाद परिणाम डाले। आपके प्रश्न के लिए, कोई डेटा एक्सेस परत अलग-अलग डीएलएस में संकलित नहीं होता है। –

उत्तर

8

अपने BusinessLogicLayer में अमूर्त BaseContext होने के बजाय, एक इंटरफ़ेस घोषित करें। फिर इसे अपने डेटा एक्सेस लेयर में कार्यान्वित करें।

public interface IDataContext : IDisposable 
{ 
    int SaveChanges(); 
} 

//Generic interface for a read-only repository 
public interface IReadOnlyRepository<T> : IDisposable where T : class 

//Generic interface for a read/write repository 
public interface IRepository<T> : IReadOnlyRepository<T> where T : class 

//Basic implementation for a read-only repository 
public abstract class BaseReadOnlyRepository<C, T> : IReadOnlyRepository<T> 
    where T : class 
    where C : IDataContext 
{ 
} 

//Basic implementation for a read/write repository 
public abstract class BaseRepository<C, T> : IRepository<T> 
    where T : class 
    where C : IDataContext 
{ 
} 


public interfaces IAccountContext : IDataContext 
{ 
    //other methods 
} 

तब डेटा का उपयोग परत

public abstract class BaseContext : DbContext, IDataContext 
{ 
    //To allow multiple contexts sharing the same connection string 
    protected BaseContext(): base("name=MyConnectionString") {} 
} 

public class AccountContext : BaseContext, IAccountContext {} 

//With this, I can have simple repositories: 

public class UserRepository : BaseRepository<AccountContext, User> 
{ //All implementation comes from the base abstract class, unless I need to change it (override methods) 
} 

आप के बजाय भंडार के अंदर संदर्भ instantiating की सेवाओं के लिए संदर्भ और भंडार सुई डि/Ioc का उपयोग कर सकते है।

यह डिकूप्लिंग आपके व्यापार तर्क परत में ईएफ असेंबली को संदर्भित करने की आवश्यकता को हटा देगा लेकिन याद रखें कि आपकी डोमेन इकाइयां ईएफ से पूरी तरह से स्वतंत्र नहीं हैं। उदाहरण के लिए नेविगेशन गुण, रिलेशनशिप फिक्स-अप ईएफ संदर्भ के बाहर काम नहीं करेंगे। तो एक तरह से आप वास्तव में एक निर्भरता छुपा रहे हैं !!

+0

वास्तव में आपके द्वारा प्रस्तावित परिवर्तनों ने मुझे एंटीटी फ्रेमवर्क का संदर्भ दिए बिना सेवा परत परियोजना को संकलित करने की अनुमति दी। मैं थोड़ी सी अटक गया हूं क्योंकि मैंने सीधे भंडार के माध्यम से संदर्भ विधियों का आह्वान करने की क्षमता खो दी है और मैं डीआई/आईओसी से बहुत परिचित नहीं हूं। मैं अपने रास्ते से काम करूंगा जहां से मैं अभी हूं। मुख्य प्रश्न का उत्तर दिया गया था। मैं यह इंगित करना चाहता हूं कि मुझे रिलेशनशिप फिक्स-अप की आवश्यकता नहीं होगी। जब आवश्यक हो तो विकल्पों को शामिल करने के साथ वस्तुओं को वापस करने के लिए भंडार जिम्मेदार होगा। तो, मेरे पीओसीओ वास्तव में केवल पीओसीओ हैं। धन्यवाद। –

संबंधित मुद्दे