এএসপি.নেট এমভিসিতে ডেটা অ্যাক্সেস পৃথক করে


35

আমি নিশ্চিত করতে চাই যে আমি এমভিসিতে আমার প্রথম আসল ক্র্যাকের সাথে শিল্পের মানগুলি এবং সেরা অনুশীলনগুলি অনুসরণ করছি। এক্ষেত্রে এটি সিএস ব্যবহার করে এটিএসপিএন নেট এমভিসি।

আমি আমার মডেলের জন্য সত্তা ফ্রেমওয়ার্ক ৪.১ ব্যবহার করব, কোড-ফার্স্ট অবজেক্ট (ডাটাবেস ইতিমধ্যে বিদ্যমান) সহ, সুতরাং ডাটাবেস থেকে ডেটা পুনরুদ্ধারের জন্য একটি ডিবিসিএনটেক্সট অবজেক্ট থাকবে।

আমি ডেমোগুলিতে আমি অ্যাসপিটনে ওয়েবসাইটে গিয়েছি, কন্ট্রোলারদের মধ্যে ডেটা অ্যাক্সেস কোড রয়েছে। এটি আমার কাছে সঠিক বলে মনে হচ্ছে না, বিশেষ করে যখন DRY অনুসরণ করুন (নিজেকে পুনরাবৃত্তি করবেন না) অনুশীলনগুলি।

উদাহরণস্বরূপ, ধরা যাক যে আমি একটি পাবলিক লাইব্রেরিতে ব্যবহার করার জন্য একটি ওয়েব অ্যাপ্লিকেশন লিখছি এবং ক্যাটালগে বই তৈরি, আপডেট এবং মুছে ফেলার জন্য আমার কাছে একটি নিয়ামক রয়েছে।

বেশ কয়েকটি ক্রিয়াকলাপ আইএসবিএন নিতে পারে এবং একটি "বুক" অবজেক্ট ফিরিয়ে দিতে চায় (এটি সম্ভবত 100% বৈধ কোড নয়) নোট করুন:

public class BookController : Controller
{
    LibraryDBContext _db = new LibraryDBContext();

    public ActionResult Details(String ISBNtoGet)
    {
        Book currentBook = _db.Books.Single(b => b.ISBN == ISBNtoGet);
        return View(currentBook);
    }

    public ActionResult Edit(String ISBNtoGet)
    {
        Book currentBook = _db.Books.Single(b => b.ISBN == ISBNtoGet);
        return View(currentBook);
    }
}

পরিবর্তে, আমার ডিবি কনটেক্সট অবজেক্টে একটি বই ফেরত দেওয়ার জন্য আসলেই আমার কোনও পদ্ধতি থাকা উচিত ? এটি মনে হয় এটি আমার কাছে আরও ভাল বিচ্ছেদ এবং DRY প্রচারে সহায়তা করে কারণ আমার ওয়েব অ্যাপ্লিকেশনটিতে অন্য কোথাও আইএসবিএন দ্বারা বুক অবজেক্ট পাওয়ার দরকার হতে পারে।

public partial class LibraryDBContext: DBContext
{
    public Book GetBookByISBN(String ISBNtoGet)
    {
        return Books.Single(b => b.ISBN == ISBNtoGet);
    }
}

public class BookController : Controller
{
    LibraryDBContext _db = new LibraryDBContext();

    public ActionResult Details(String ISBNtoGet)
    {
        return View(_db.GetBookByISBN(ISBNtoGet));
    }

    public ActionResult Edit(ByVal ISBNtoGet as String)
    {
        return View(_db.GetBookByISBN(ISBNtoGet));
    }
}

আমার অ্যাপ্লিকেশনটির কোডিংয়ে অনুসরণ করার জন্য এটি কি কোনও বৈধ সেট?

বা, আমার ধারণা আরও একটি বিষয়গত প্রশ্ন হবে: "এটি কি এটি সঠিক উপায়?"

উত্তর:


55

সাধারণত, আপনি চান আপনার কন্ট্রোলাররা কেবলমাত্র কয়েকটি জিনিস করুক:

  1. আগত অনুরোধটি পরিচালনা করুন
  2. কিছু ব্যবসায়ের উদ্দেশ্যে প্রসেসিং ডেলিগেট করুন
  3. ব্যবসায়িক প্রক্রিয়াজাতকরণের ফলাফলটি রেন্ডারিংয়ের জন্য উপযুক্ত দৃশ্যে পাস করুন

নিয়ামকটিতে কোনও ডেটা অ্যাক্সেস বা জটিল ব্যবসার যুক্তি থাকা উচিত নয় ।

[সাধারণ অ্যাপ্লিকেশনগুলিতে, আপনি সম্ভবত আপনার নিয়ামকটিতে বেসিক ডেটা সিআরইউডি ক্রিয়াকলাপগুলি থেকে সরে যেতে পারেন, তবে একবার আপনি সাধারণ গেট এবং আপডেট কলগুলি যুক্ত করা শুরু করার পরে, আপনি আপনার প্রক্রিয়াটি আলাদা শ্রেণিতে বিভক্ত করতে চাইবেন। ]

আপনার নিয়ামকরা প্রকৃত প্রসেসিংয়ের কাজটি করার জন্য সাধারণত কোনও 'পরিষেবা' এর উপর নির্ভর করে। আপনার পরিষেবা শ্রেণিতে আপনি সরাসরি আপনার ডেটা উত্সের সাথে কাজ করতে পারেন (আপনার ক্ষেত্রে, ডিবি কনটেক্সট) তবে আবার যদি আপনি নিজেকে ডেটা অ্যাক্সেসের পাশাপাশি প্রচুর ব্যবসার নিয়ম লিখতে দেখেন তবে আপনি সম্ভবত আপনার ব্যবসা আলাদা করতে চাইবেন আপনার ডেটা অ্যাক্সেস থেকে যুক্তি।

এই মুহুর্তে, আপনার সম্ভবত একটি ক্লাস থাকবে যা ডেটা অ্যাক্সেস ছাড়া কিছুই করে না। কখনও কখনও এটিকে একটি সংগ্রহস্থল বলা হয় তবে নামটি কী তা তা আসলেই আসে না। মুল বক্তব্যটি হ'ল ডেটাবেসটির ভেতর থেকে ডেটা পাওয়ার জন্য সমস্ত কোড এক জায়গায়।

আমি যে এমভিসি প্রকল্পে কাজ করেছি তার জন্য আমি সর্বদা এর মতো কাঠামো দিয়ে শেষ করেছি:

নিয়ামক

public class BookController : Controller
{
    ILibraryService _libraryService;

    public BookController(ILibraryService libraryService)
    {
        _libraryService = libraryService;
    }

    public ActionResult Details(String isbn)
    {
        Book currentBook = _libraryService.RetrieveBookByISBN(isbn);
        return View(ConvertToBookViewModel(currentBook));
    }

    public ActionResult DoSomethingComplexWithBook(ComplexBookActionRequest request)
    {
        var responseViewModel = _libraryService.ProcessTheComplexStuff(request);
        return View(responseViewModel);
    }
}

ব্যবসা সেবা

public class LibraryService : ILibraryService
{
     IBookRepository _bookRepository;
     ICustomerRepository _customerRepository;

     public LibraryService(IBookRepository bookRepository, 
                           ICustomerRepository _customerRepository )
     {
          _bookRepository = bookRepository;
          _customerRepository = customerRepository;
     }

     public Book RetrieveBookByISBN(string isbn)
     {
          return _bookRepository.GetBookByISBN(isbn);
     }

     public ComplexBookActionResult ProcessTheComplexStuff(ComplexBookActionRequest request)
     {
          // Possibly some business logic here

          Book book = _bookRepository.GetBookByISBN(request.Isbn);
          Customer customer = _customerRepository.GetCustomerById(request.CustomerId);

          // Probably more business logic here

          _libraryRepository.Save(book);

          return complexBusinessActionResult;

     } 
}

সংগ্রহস্থলের প্রয়োগ

public class BookRepository : IBookRepository
{
     LibraryDBContext _db = new LibraryDBContext();

     public Book GetBookByIsbn(string isbn)
     {
         return _db.Books.Single(b => b.ISBN == isbn);
     }

     // And the rest of the data access
}

+1 সামগ্রিকভাবে দুর্দান্ত পরামর্শ, যদিও আমি জিজ্ঞাসা করব যে সংগ্রহস্থল বিমূর্তি কোনও মান সরবরাহ করছিল কিনা।
ম্যাটড্যাভে

3
@ ম্যাটড্যাভে হ্যাঁ, একেবারে গোড়ার দিকে (বা অ্যাপ্লিকেশনগুলির সর্বাধিক সহজ) জন্য একটি রিপোজিটরি স্তরটির প্রয়োজনীয়তা দেখতে পাওয়া শক্ত, তবে আপনার ব্যবসায়ের যুক্তিতে আপনার মাঝারি ধরণের জটিলতা হওয়ার সাথে সাথে এটি কোনও মস্তিষ্কে পরিণত হয় না ডেটা অ্যাক্সেস পৃথক করুন। যদিও এটি সহজ উপায়ে জানানো সহজ নয়।
এরিক কিং

1
@Billy আইওসি কার্নেল নেই আছে MVC প্রকল্পে যাবে। আপনি এটির নিজস্ব একটি প্রকল্পে এটি থাকতে পারেন, যা এমভিসি প্রকল্পের উপর নির্ভর করে, তবে যা পরিবর্তিত সংগ্রহস্থল প্রকল্পের উপর নির্ভর করে। আমি সাধারণত এটি করি না কারণ আমার প্রয়োজন বোধ হয় না। তবুও, আপনি যদি চান না যে আপনার এমভিসি প্রকল্পটি আপনার সংগ্রহশালা ক্লাস করতে পারে ... তবে তা করবেন না। আমি নিজেকে হ্যামস্ট্রিংয়ের খুব বড় অনুরাগী না যাতে আমি নিজেকে প্রোগ্রামিংয়ের অনুশীলনগুলির থেকে নিজেকে রক্ষা করতে পারি যা আমি সম্ভবত জড়িত না।
এরিক কিং

2
আমরা ঠিক এই প্যাটার্নটি ব্যবহার করি: নিয়ন্ত্রক-পরিষেবা-সংগ্রহস্থল Rep আমি যুক্ত করতে চাই যে আমাদের জন্য পরিষেবা / সংগ্রহশালা স্তর প্যারামিটার অবজেক্টগুলি গ্রহণ করা (উদাহরণস্বরূপ গেটবুকপ্যারামিটারস) নেওয়া এবং তারপরে প্যারামিটার র‌্যাংলিংয়ের জন্য ILibraryService এ এক্সটেনশন পদ্ধতিগুলি ব্যবহার করা খুব দরকারী useful এইভাবে আইলিবেরি সার্ভিসারে একটি সহজ এন্ট্রি পয়েন্ট রয়েছে যা কোনও অবজেক্ট নিয়ে যায় এবং এক্সটেনশন পদ্ধতিটি প্রতিবার ইন্টারফেস এবং ক্লাসগুলি পুনরায় লিখতে না পেরে প্যারামিটার হিসাবে পাগল হয়ে যেতে পারে (যেমন গেটবুকস বাইসআইবিএন / গ্রাহক / তারিখ / যা কেবল গেটবুকপ্যারামিটার অবজেক্ট গঠন করে এবং কল করে সেবা)। কম্বো দুর্দান্ত হয়েছে।
ব্ল্যাকজ্যাককেট

1
@ ইসাকাক্লেইনম্যান আমাকে কোনটি গ্রেট লিখেছেন তা মনে করতে পারি না (বব মার্টিন?) তবে এটি একটি মৌলিক প্রশ্ন: আপনি ওভেন.বেক (পিজ্জা) বা পিজ্জা.বেক (ওভেন) চান? এবং উত্তরটি 'এটি নির্ভর করে'। সাধারণত আমরা এক বা একাধিক অবজেক্ট (বা পিজ্জা!) চালিত করার জন্য বাইরের পরিষেবা (বা কাজের একক) চাই। তবে কে বলবেন যে এই সমস্ত পৃথক বস্তুর ওভেন যেভাবে বেকড হচ্ছে সে সম্পর্কে প্রতিক্রিয়া জানানোর ক্ষমতা রাখে না I আমি অর্ডার.সেপ (অর্ডার) -এ সংরক্ষণ করুন (সংরক্ষণ করুন) -এ পছন্দ করুন। যাইহোক, আমি অর্ডার.ভালিডেট () এর মতো করি কারণ আদেশটি এটি নিজের আদর্শ রূপটি জানতে পারে। প্রাসঙ্গিক এবং ব্যক্তিগত।
ব্ল্যাকজ্যাককেট

2

এটি আমি এভাবেই করছি, যদিও আমি জেনেরিক ডেটা পরিষেবা ইন্টারফেস হিসাবে ডেটা সরবরাহকারীকে ইনজেকশন দিচ্ছি যাতে আমি বাস্তবায়নগুলি সরিয়ে নিতে পারি।

আমি যতদূর জানি, নিয়ামকটি হ'ল আপনি যেখানে ডেটা পাবেন, কোনও ক্রিয়া সম্পাদন করবেন এবং ডেটা ভিউতে প্রেরণ করবেন।


হ্যাঁ, আমি ডেটা সরবরাহকারীর জন্য "পরিষেবা ইন্টারফেস" ব্যবহার সম্পর্কে পড়েছি কারণ এটি ইউনিট পরীক্ষায় সহায়তা করে।
scott.korin
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.