আইএমও Repository
বিমূর্ততা এবং বিমূর্ততা উভয় UnitOfWork
অর্থপূর্ণ বিকাশে একটি খুব মূল্যবান স্থান আছে have লোকেরা বাস্তবায়নের বিশদ সম্পর্কে তর্ক করবে, তবে যেমন একটি বিড়ালকে ত্বকে নেওয়ার বিভিন্ন উপায় রয়েছে, তেমনি বিমূর্তি বাস্তবায়নেরও অনেক উপায় রয়েছে।
আপনার প্রশ্নটি বিশেষভাবে ব্যবহার করার জন্য বা ব্যবহার না করার জন্য এবং কেন।
আপনি কোন সন্দেহ বুঝতে পেরেছি হিসাবে আপনি ইতিমধ্যে উভয় এই নিদর্শন সত্তা ফ্রেমওয়ার্ক পাতাটা আছে DbContext
হয় UnitOfWork
এবং DbSet
হয় Repository
। আপনি সাধারণত ইউনিট পরীক্ষা করার প্রয়োজন হবে না UnitOfWork
বা Repository
তারা কেবল আপনার ক্লাস এবং অন্তর্নিহিত ডেটা অ্যাক্সেস বাস্তবায়নের মধ্যে সুবিধা হয় নিজেদের। আপনার পরিষেবাগুলির যুক্তি পরীক্ষা করার সময় আপনি যখন নিজেকে বার বার প্রয়োজন হবে তা হ'ল এই দুটি বিমূর্ততাটিকে উপহাস করে।
আপনি লক এবং পরীক্ষার জন্য যুক্তিটির মধ্যে কোড নির্ভরতাগুলির স্তরগুলি (যা আপনি নিয়ন্ত্রণ করেন না) যুক্ত করে বহিরাগত লাইব্রেরিগুলির সাথে আপনি উপহাস, জাল বা যা কিছু করতে পারেন ।
সুতরাং একটি ছোটখাটো বিষয় হ'ল আপনার ইউনিট পরীক্ষাগুলি উপহাস করার সময় আপনার নিজস্ব বিমূর্ততা থাকা UnitOfWork
এবং Repository
আপনাকে সর্বাধিক নিয়ন্ত্রণ এবং নমনীয়তা দেয়।
সব কিছু খুব ভাল, তবে আমার কাছে, এই বিমূর্ততার আসল শক্তি হ'ল এএসপেক্ট ওরিয়েন্টেড প্রোগ্রামিং কৌশলগুলি প্রয়োগ করার এবং সলিড নীতিগুলি মেনে চলার একটি সহজ উপায় ।
সুতরাং আপনি আপনার IRepository
:
public interface IRepository<T>
where T : class
{
T Add(T entity);
void Delete(T entity);
IQueryable<T> AsQueryable();
}
এবং এর বাস্তবায়ন:
public class Repository<T> : IRepository<T>
where T : class
{
private readonly IDbSet<T> _dbSet;
public Repository(PPContext context)
{
_dbSet = context.Set<T>();
}
public T Add(T entity)
{
return _dbSet.Add(entity);
}
public void Delete(T entity)
{
_dbSet.Remove(entity);
}
public IQueryable<T> AsQueryable()
{
return _dbSet.AsQueryable();
}
}
সাধারণের বাইরে এখন পর্যন্ত কিছুই নেই তবে এখন আমরা কিছু লগিং যুক্ত করতে চাই - লগিং ডেকরেটারের সাহায্যে সহজ ।
public class RepositoryLoggerDecorator<T> : IRepository<T>
where T : class
{
Logger logger = LogManager.GetCurrentClassLogger();
private readonly IRepository<T> _decorated;
public RepositoryLoggerDecorator(IRepository<T> decorated)
{
_decorated = decorated;
}
public T Add(T entity)
{
logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString() );
T added = _decorated.Add(entity);
logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString());
return added;
}
public void Delete(T entity)
{
logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString());
_decorated.Delete(entity);
logger.Log(LogLevel.Debug, () => DateTime.Now.ToLongTimeString());
}
public IQueryable<T> AsQueryable()
{
return _decorated.AsQueryable();
}
}
সবই করা হয়েছে এবং আমাদের বিদ্যমান কোডটিতে কোনও পরিবর্তন নেই । আমরা যুক্ত করতে পারি এমন আরও অনেক ক্রস উদ্বেগ রয়েছে যেমন ব্যতিক্রম হ্যান্ডলিং, ডেটা ক্যাশিং, ডেটা যাচাইকরণ বা যা কিছু এবং আমাদের ডিজাইন এবং বিল্ড প্রসেসের মধ্যে আমাদের কাছে সবচেয়ে মূল্যবান জিনিস যা আমাদের বিদ্যমান কোডের কোনও পরিবর্তন না করেই সাধারণ বৈশিষ্ট্যগুলি যুক্ত করতে সক্ষম করে আমাদের IRepository
বিমূর্ততা ।
এখন, স্ট্যাকওভারফ্লোতে আমি এই প্রশ্নটি অনেকবার দেখেছি - "আপনি কীভাবে বহু ভাড়াটে পরিবেশে এন্টি ফ্রেমওয়ার্ককে কাজ করবেন?"
https://stackoverflow.com/search?q=%5 Bentity-framework%5D+ মাল্টি +++
আপনার যদি কোনও Repository
বিমূর্ততা থাকে তবে উত্তরটি হ'ল "এটি সহজেই একটি সাজসজ্জা যুক্ত করুন"
public class RepositoryTennantFilterDecorator<T> : IRepository<T>
where T : class
{
public readonly IRepository<T> _decorated;
public RepositoryTennantFilterDecorator(IRepository<T> decorated)
{
_decorated = decorated;
}
public T Add(T entity)
{
return _decorated.Add(entity);
}
public void Delete(T entity)
{
_decorated.Delete(entity);
}
public IQueryable<T> AsQueryable()
{
return _decorated.AsQueryable().Where(o => true);
}
}
আইএমও আপনার সর্বদা কোনও তৃতীয় পক্ষের উপাদানগুলির উপরে একটি সরল বিমূর্ততা স্থাপন করা উচিত যা মুষ্টিমেয় জায়গাগুলির চেয়েও বেশি জায়গায় রেফারেন্স করা হবে। এই দৃষ্টিকোণ থেকে একটি ORM হ'ল নিখুঁত প্রার্থী হিসাবে এটি আমাদের কোডের অনেকগুলিতে উল্লেখ করা হয়।
উত্তরটি সাধারণত মনে আসে যখন কেউ বলে যে "কেন Repository
এই বা তৃতীয় পক্ষের লাইব্রেরিটির উপরে আমার বিমূর্ততা (উদাহরণস্বরূপ ) হওয়া উচিত " "আপনি কেন করবেন না?"
পিএস ডেকোরেটরগুলি আইওসি পাত্রে যেমন সিম্পল ইনজেক্টর ব্যবহার করে আবেদন করা অত্যন্ত সহজ ।
[TestFixture]
public class IRepositoryTesting
{
[Test]
public void IRepository_ContainerRegisteredWithTwoDecorators_ReturnsDecoratedRepository()
{
Container container = new Container();
container.RegisterLifetimeScope<PPContext>();
container.RegisterOpenGeneric(
typeof(IRepository<>),
typeof(Repository<>));
container.RegisterDecorator(
typeof(IRepository<>),
typeof(RepositoryLoggerDecorator<>));
container.RegisterDecorator(
typeof(IRepository<>),
typeof(RepositoryTennantFilterDecorator<>));
container.Verify();
using (container.BeginLifetimeScope())
{
var result = container.GetInstance<IRepository<Image>>();
Assert.That(
result,
Is.InstanceOf(typeof(RepositoryTennantFilterDecorator<Image>)));
Assert.That(
(result as RepositoryTennantFilterDecorator<Image>)._decorated,
Is.InstanceOf(typeof(RepositoryLoggerDecorator<Image>)));
}
}
}