रिपोजिटरी और सर्विस लेयर के बीच अंतर?


189

OOP डिजाइन पैटर्न में, रिपॉजिटरी पैटर्न और एक सर्विस लेयर में क्या अंतर है?

मैं एक ASP.NET MVC 3 ऐप पर काम कर रहा हूं, और मैं इन डिज़ाइन पैटर्न को समझने की कोशिश कर रहा हूं, लेकिन मेरा दिमाग अभी नहीं मिल रहा है ... फिर भी !!

जवाबों:


330

रिपॉजिटरी लेयर आपको डेटा के उपयोग पर अतिरिक्त स्तर प्रदान करता है। लिखने के बजाय

var context = new DatabaseContext();
return CreateObjectQuery<Type>().Where(t => t.ID == param).First();

डेटाबेस से एकल आइटम प्राप्त करने के लिए, आप रिपॉजिटरी इंटरफ़ेस का उपयोग करते हैं

public interface IRepository<T>
{
    IQueryable<T> List();
    bool Create(T item);
    bool Delete(int id);
    T Get(int id);
    bool SaveChanges();
}

और कॉल करें Get(id)। रिपोजिटरी परत बुनियादी सीआरयूडी ऑपरेशन को उजागर करती है ।

सेवा परत व्यावसायिक तर्क को उजागर करती है, जो भंडार का उपयोग करती है। उदाहरण सेवा की तरह लग सकता है:

public interface IUserService
{
    User GetByUserName(string userName);
    string GetUserNameByEmail(string email);
    bool EditBasicUserData(User user);
    User GetUserByID(int id);
    bool DeleteUser(int id);
    IQueryable<User> ListUsers();
    bool ChangePassword(string userName, string newPassword);
    bool SendPasswordReminder(string userName);
    bool RegisterNewUser(RegisterNewUserModel model);
}

जबकि List()रिपॉजिटरी का तरीका सभी यूजर्स का है, ListUsers()IUserService की ही वापसी हो सकती है, यूजर की पहुंच है।

ASP.NET MVC + EF + SQL सर्वर में, मेरे पास संचार का यह प्रवाह है:

दृश्य <- नियंत्रक -> सेवा परत -> रिपॉजिटरी परत -> ईएफ -> एसक्यूएल सर्वर

सेवा परत -> रिपॉजिटरी परत -> ईएफ यह भाग मॉडल पर संचालित होता है।

दृश्य <- नियंत्रक -> सेवा परत यह भाग दृश्य मॉडलों पर संचालित होता है।

संपादित करें:

के लिए प्रवाह का उदाहरण / आदेश / ByClient / 5 (हम विशिष्ट ग्राहक के लिए आदेश देखना चाहते हैं):

public class OrderController
{
    private IOrderService _orderService;

    public OrderController(IOrderService orderService)
    {
        _orderService = orderService; // injected by IOC container
    }

    public ActionResult ByClient(int id)
    {
        var model = _orderService.GetByClient(id);
        return View(model); 
    }
}

यह ऑर्डर सेवा के लिए इंटरफ़ेस है:

public interface IOrderService
{
    OrdersByClientViewModel GetByClient(int id);
}

यह इंटरफ़ेस दृश्य मॉडल लौटाता है:

public class OrdersByClientViewModel
{
     CientViewModel Client { get; set; } //instead of ClientView, in simple project EF Client class could be used
     IEnumerable<OrderViewModel> Orders { get; set; }
}

यह इंटरफ़ेस कार्यान्वयन है। यह दृश्य मॉडल बनाने के लिए मॉडल कक्षाओं और रिपॉजिटरी का उपयोग करता है:

public class OrderService : IOrderService
{
     IRepository<Client> _clientRepository;
     public OrderService(IRepository<Client> clientRepository)
     {
         _clientRepository = clientRepository; //injected
     }

     public OrdersByClientViewModel GetByClient(int id)
     {
         return _clientRepository.Get(id).Select(c => 
             new OrdersByClientViewModel 
             {
                 Cient = new ClientViewModel { ...init with values from c...}
                 Orders = c.Orders.Select(o => new OrderViewModel { ...init with values from o...}     
             }
         );
     }
}

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

81
सेवा में दृश्य मॉडल वापस क्यों करें? यदि आप एक से अधिक ग्राहक (मोबाइल / वेब) के लिए सेवा का अनुकरण नहीं करते हैं? यदि मामला ऐसा है तो दृश्यमोडल अलग-अलग प्लेटफार्मों से अलग हो सकता है
रयान

12
@ रेयान के साथ सहमत, सेवा परत को इकाई ऑब्जेक्ट या इकाई ऑब्जेक्ट्स का संग्रह वापस करना चाहिए (IQueryable नहीं)। उदाहरण के लिए आटोमैपर द्वारा SomeViewModel के लिए ui संस्था के नक्शे पर।
एल्डर

5
@ डफ: आपको प्रत्येक इकाई के लिए रिपॉजिटरी बनाने की आवश्यकता नहीं है। आप सामान्य कार्यान्वयन और बाँध का उपयोग कर सकते IRepository<>करने के लिए GenericRepository<>अपने आईओसी पुस्तकालय में। यह उत्तर बहुत पुराना है। मुझे लगता है कि सबसे अच्छा समाधान सभी रिपॉजिटरी को एक वर्ग में संयोजित करना है UnitOfWork। इसमें हर प्रकार का भंडार और एक विधि कहा जाना चाहिए SaveChanges। सभी रिपॉजिटरी को एक ईएफ संदर्भ साझा करना चाहिए।
लुकलेड

2
सेवा परत से दृश्यमॉडल वापस करने के बजाय, आपको डीटीओ वापस करना चाहिए और उस दृश्य को ऑटोमैप्पर का उपयोग करके परिवर्तित करना चाहिए .. कभी-कभी वे एक ही होते हैं, जब वे नहीं होते हैं तो आप आभारी होंगे कि आपने YGTNI को लागू किया है "आप जा रहे हैं" नीड इट ”
हेंज़ोलो

41

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

दूसरी ओर सर्विस लेयर का उद्देश्य कोड के पुन: उपयोग और चिंताओं के पृथक्करण को बढ़ावा देने के लिए व्यापार तर्क को एक ही स्थान पर संलग्न करना है। एस्पेक्ट एमवीसी साइटों के निर्माण के दौरान आमतौर पर व्यवहार में मेरे लिए इसका मतलब यह है कि मेरे पास यह संरचना है

[नियंत्रक] कॉल [सेवा (ओं)] जो कॉल [रिपॉजिटरी (ies)]

एक सिद्धांत जो मैंने उपयोगी पाया है, वह है कि लॉजिक को कम से कम कंट्रोलर्स और रिपॉजिटरी में रखना।

नियंत्रकों में यह है क्योंकि यह मुझे DRY रखने में मदद करता है। यह बहुत सामान्य है कि मुझे उसी फ़िल्टरिंग या तर्क का उपयोग कहीं और करने की आवश्यकता है और यदि मैंने इसे नियंत्रक में रखा है तो मैं इसका पुन: उपयोग नहीं कर सकता।

रिपॉजिटरी में यह इसलिए है क्योंकि मैं अपने स्टोरेज (या ओआरएम) को बदलने में सक्षम होना चाहता हूं जब कुछ बेहतर होता है। और अगर मेरे पास रिपॉजिटरी में तर्क है तो मुझे रिपॉजिटरी बदलने पर इस लॉजिक को फिर से लिखना होगा। यदि मेरी रिपॉजिटरी केवल IQueryable लौटाती है और सेवा दूसरी तरफ फ़िल्टरिंग करती है, तो मुझे केवल मैपिंग को बदलने की आवश्यकता होगी।

उदाहरण के लिए मैंने हाल ही में अपने कई Linq-To-Sql रिपॉजिटरी को EF4 के साथ बदल दिया और उन लोगों को जहां मैं इस सिद्धांत के लिए सही था, कुछ ही मिनटों में बदल सकते थे। जहां मेरे पास कुछ तर्क थे, यह बजाय घंटे की बात थी।


मैं आपकी बात से सहमत हूँ। वास्तव में, मैंने अपने टेक ब्लॉग freecodebase.com में एक ही परिदृश्य लागू किया है और मैंने इस कार्यान्वयन में कोड पहले दृष्टिकोण का उपयोग किया है। सोर्स कोड को यहां भी डाउनलोड किया जा सकता है।
टॉफी

मैं एक मौजूदा MVC ऐप में रिपॉजिटरी पैटर्न लागू करने के सामान्य विषय पर शोध कर रहा हूं। यह एक सक्रिय रिकॉर्ड-जैसे ORM और अन्य रेल / लारवेल सम्मेलनों के साथ एक bespoke फ्रेमवर्क है, और अब मैं जो काम कर रहा हूं उसके लिए कुछ वास्तु समस्याएं हैं। एक बात जो मुझे पता चली है वह यह है कि रिपॉजिटरी "व्यूमाडल्स, डीटीओ, या क्वेरी ऑब्जेक्ट्स को वापस नहीं करना चाहिए", बल्कि रिपॉजिटरी ऑब्जेक्ट्स को वापस करना चाहिए। मैं सोच रहा हूँ कि सेवाओं के माध्यम से रिपॉजिटरी ऑब्जेक्ट्स के साथ बातचीत कैसे की onBeforeBuildBrowseQueryजा सकती है और क्वेरी को बदलने के लिए क्वेरी बिल्डर का उपयोग कर सकते हैं।
सुलेख-io

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

24

स्वीकृत उत्तर (और सैकड़ों बार उत्कीर्ण) का एक प्रमुख दोष है। मैं इस टिप्पणी में इंगित करना चाहता था, लेकिन यह सिर्फ 30 टिप्पणियों में नीचे दफन हो जाएगा इसलिए यहाँ इंगित करता है।

मैंने एक एंटरप्राइज़ एप्लिकेशन लिया जो उस तरह से बनाया गया था और मेरी प्रारंभिक प्रतिक्रिया WTH थी ? सेवा परत में ViewModels? मैं अधिवेशन को बदलना नहीं चाहता था क्योंकि विकास के वर्षों में यह चला गया था इसलिए मैंने ViewModels को वापस करना जारी रखा। लड़का यह दुःस्वप्न में बदल गया जब हमने WPF का उपयोग शुरू किया। हम (देवों की टीम) हमेशा कह रहे थे: कौन सा व्यूमॉडल? वास्तविक एक (जिसे हमने WPF के लिए लिखा था) या सेवाएं एक? वे एक वेब एप्लिकेशन के लिए लिखे गए थे और यहां तक कि यूआई में संपादन को अक्षम करने के लिए IsReadOnly ध्वज था । प्रमुख, प्रमुख दोष और सभी एक शब्द के कारण: ViewModel !!

इससे पहले कि आप वही गलती करें, ऊपर मेरी कहानी के अलावा कुछ और कारण दिए गए हैं:

सेवा स्तर से एक ViewModel लौटना एक बहुत बड़ी संख्या है। यह कहने जैसा है:

  1. यदि आप इन सेवाओं का उपयोग करना चाहते हैं तो आप बेहतर तरीके से MVVM का उपयोग कर सकते हैं और यहाँ ViewModel है जिसका आपको उपयोग करने की आवश्यकता है। आउच!

  2. सेवाएं यह धारणा बना रही हैं कि उन्हें कहीं यूआई में प्रदर्शित किया जाएगा। यदि यह गैर-यूआई एप्लिकेशन जैसे कि वेब सेवाओं या विंडोज़ सेवाओं द्वारा उपयोग किया जाता है तो क्या होगा?

  3. यह भी एक वास्तविक ViewModel नहीं है। एक वास्तविक ViewModel में अवलोकनशीलता, आज्ञाएं आदि हैं जो एक बुरे नाम के साथ सिर्फ एक POCO है। (नाम क्यों मायने रखता है के लिए ऊपर मेरी कहानी देखें।)

  4. खपत आवेदन बेहतर एक प्रस्तुति परत हो (ViewModels इस परत द्वारा उपयोग किया जाता है) और यह C # को बेहतर ढंग से समझता है। एक और आउच!

कृपया, ऐसा मत करो!


3
मुझे बस इस पर टिप्पणी करनी थी, हालांकि मुझे पता है कि यह चर्चा में शामिल नहीं होता है: "यह एक बुरे नाम के साथ सिर्फ एक पीओसीओ है।" << - कि टी शर्ट पर अच्छा लगेगा! :) :)
Mephisztoe

8

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


इसलिए ASP.NET MVC ऐप में EF4 का उपयोग करते हुए, शायद कुछ इस तरह से हो: SQL Server -> EF4 -> रिपॉजिटरी -> सर्विस लेयर -> मॉडल -> नियंत्रक और इसके विपरीत?
सैम

1
हाँ, आपके भंडार का उपयोग EF4 से हल्के निकाय प्राप्त करने के लिए किया जा सकता है; और आपकी सेवा परत का उपयोग एक विशेष मॉडल प्रबंधक (आपके परिदृश्य में मॉडल) को वापस भेजने के लिए किया जा सकता है। नियंत्रक ऐसा करने के लिए आपके विशेष मॉडल प्रबंधक को कॉल करेगा ... Mvc 2/3 के लिए मेरे ब्लॉग पर एक त्वरित नज़र डालें। मेरे पास आरेख हैं।
कार्नेकोड

केवल स्पष्टीकरण के लिए: आपके परिदृश्य में EF4 वह जगह है जहाँ मॉडल मेरे आरेखों पर है और आपके परिदृश्य में मॉडल मेरे आरेखों में विशिष्ट मॉडल प्रबंधक हैं
CarneyCode

4

डेटाबेस तक पहुँचने के लिए रिपॉजिटरी लेयर को लागू किया जाता है और डेटाबेस पर CRUD के संचालन को बढ़ाने में मदद करता है। जबकि एक सर्विस लेयर में एप्लिकेशन के व्यावसायिक तर्क होते हैं और डेटाबेस से जुड़े कुछ लॉजिक को लागू करने के लिए रिपॉजिटरी लेयर का उपयोग कर सकते हैं। एक आवेदन में, एक अलग रिपॉजिटरी परत और सेवा परत होना बेहतर है। अलग रिपॉजिटरी और सर्विस लेयर्स होने से कोड अधिक माड्यूलर हो जाता है और डेटाबेस को बिजनेस लॉजिक से अलग कर देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.