দ্রষ্টব্য: এই উত্তরটি সত্তা ফ্রেমওয়ার্ক সম্পর্কে আলোচনা করে DbContext
তবে এটি কার্যকরীকরণের যে কোনও ইউনিট যেমন এসকিউএল এর DataContext
লিনকিউ এবং এনএইচবারনেটের ক্ষেত্রে প্রযোজ্য ISession
।
ইয়ান প্রতিধ্বনি দিয়ে শুরু করা যাক: DbContext
পুরো অ্যাপ্লিকেশনটির জন্য একটি একক থাকা খারাপ ধারণা। আপনি যখন একটি একক থ্রেডযুক্ত অ্যাপ্লিকেশন এবং ডেটাবেসগুলি সম্পূর্ণরূপে সেই একক অ্যাপ্লিকেশন উদাহরণ দ্বারা ব্যবহার করেন তখন এটি কেবল তখনই বোঝা যায়। DbContext
থ্রেড-নিরাপদ এবং নয় এবং যেহেতু DbContext
ক্যাশে ডেটা, এটা মামুলি বেশ তাড়াতাড়ি পায়। একাধিক ব্যবহারকারী / অ্যাপ্লিকেশনগুলি সেই ডাটাবেসে একসাথে কাজ করার সময় এটি (যা অবশ্যই খুব সাধারণ) আপনি সমস্ত প্রকার সমস্যায় পড়বেন। তবে আমি আশা করি আপনি এটি ইতিমধ্যে জেনে গেছেন এবং কেবল এটি কেন জানতে চান যে প্রয়োজনের যে কোনও ব্যক্তির মধ্যে একটি নতুন উদাহরণ (অর্থাত্ একটি ক্ষণস্থায়ী জীবনধারা সহ) কেন ইনজেক্ট করবেন DbContext
না। (কেন DbContext
প্রতিটি থ্রেড প্রসঙ্গে একটি একক -অন কেন খারাপ তা সম্পর্কে আরও তথ্যের জন্য , এই উত্তরটি পড়ুন )।
আমাকে এই বলে শুরু করে চলুন যে DbContext
ক্ষণস্থায়ী হিসাবে নিবন্ধকরণ কাজ করতে পারে তবে সাধারণত আপনি নির্দিষ্ট ক্ষেত্রের মধ্যে এই জাতীয় ইউনিটের কাজের একক উদাহরণ থাকতে চান। একটি ওয়েব অ্যাপ্লিকেশনটিতে, এটি একটি ওয়েব অনুরোধের সীমানায় যেমন একটি সুযোগকে সংজ্ঞায়িত করা ব্যবহারিক হতে পারে; এইভাবে প্রতি ওয়েব অনুরোধ জীবনধারা। এটি আপনাকে একই প্রসঙ্গে বস্তুর পুরো সেটটি পরিচালনা করতে দেয়। অন্য কথায়, তারা একই ব্যবসায়িক লেনদেনের মধ্যে পরিচালনা করে।
একই প্রসঙ্গে যদি আপনার কোনও সেট অপারেশন পরিচালনার কোনও লক্ষ্য না থাকে তবে সেক্ষেত্রে ক্ষণস্থায়ী জীবনধারা ভাল, তবে দেখার মতো কয়েকটি বিষয় রয়েছে:
- যেহেতু প্রতিটি বস্তুর নিজস্ব উদাহরণ পাওয়া যায়, প্রতিটি শ্রেণি যা সিস্টেমের অবস্থার পরিবর্তন করে, তাদের কল করতে হবে
_context.SaveChanges()
(অন্যথায় পরিবর্তনগুলি হারিয়ে যাবে)। এটি আপনার কোডকে জটিল করে তুলতে পারে এবং কোডে একটি দ্বিতীয় দায়িত্ব যুক্ত করে (প্রসঙ্গ নিয়ন্ত্রণের দায়িত্ব), এবং এটি একক দায়িত্বের নীতি লঙ্ঘন ।
- আপনাকে নিশ্চিত করতে হবে যে সত্ত্বাগুলি [একটি দ্বারা বোঝা এবং সংরক্ষণ করা
DbContext
] কখনই এই ধরণের শ্রেণির সুযোগ ছেড়ে যায় না, কারণ সেগুলি অন্য শ্রেণীর প্রসঙ্গে দেখা যায় না। এটি আপনার কোডটিকে অত্যন্ত জটিল করে তুলতে পারে, কারণ যখন আপনাকে এই সত্তাগুলির প্রয়োজন হয় তখন আপনাকে আবার আইডি দিয়ে এগুলি লোড করা দরকার যা পারফরম্যান্সেও সমস্যা তৈরি করতে পারে।
- যেহেতু
DbContext
কার্যকরী IDisposable
, আপনি সম্ভবত এখনও পর্যন্ত সব নির্মিত দৃষ্টান্ত নষ্ট করতে চাই। আপনি যদি এটি করতে চান তবে আপনার কাছে মূলত দুটি বিকল্প রয়েছে। কল করার পরে আপনাকে সেগুলি একই পদ্ধতিতে নিষ্পত্তি করতে হবে context.SaveChanges()
, তবে সেই ক্ষেত্রে ব্যবসায়ের যুক্তি এমন কোনও বস্তুর মালিকানা নেয় যা বাইরে থেকে পাস করা হয়। দ্বিতীয় বিকল্পটি হ'ল এইচটিটিপি অনুরোধের সীমানায় তৈরি হওয়া সমস্ত দৃষ্টান্তগুলি নিষ্পত্তি করা, তবে সেই ক্ষেত্রে সেই সমস্ত দৃষ্টিকোণগুলি নিষ্পত্তি করার দরকার পরে কনটেইনারটি আপনাকে জানাতে কিছু ধরণের স্কোপিং প্রয়োজন।
আরেকটি বিকল্প হ'ল একেবারে ইনজেক্ট না করাDbContext
। পরিবর্তে, আপনি DbContextFactory
এমন একটি ইনজেকশন করুন যা একটি নতুন উদাহরণ তৈরি করতে সক্ষম হয় (আমি আগে এই পদ্ধতির ব্যবহার করতাম)। এইভাবে ব্যবসায়ের যুক্তি প্রসঙ্গে সুস্পষ্টভাবে নিয়ন্ত্রণ করে। যদি দেখতে এই মত হতে পারে:
public void SomeOperation()
{
using (var context = this.contextFactory.CreateNew())
{
var entities = this.otherDependency.Operate(
context, "some value");
context.Entities.InsertOnSubmit(entities);
context.SaveChanges();
}
}
এর অতিরিক্ত দিক হ'ল আপনি DbContext
সুস্পষ্টভাবে জীবন পরিচালনা করেন এবং এটি সেট আপ করা সহজ। এটি আপনাকে নির্দিষ্ট স্কোপগুলিতে একটি একক প্রসঙ্গও ব্যবহার করতে দেয়, যার স্পষ্ট সুবিধা রয়েছে যেমন একটি একক ব্যবসায়িক লেনদেনে কোড চালানো, এবং সত্তাগুলির কাছাকাছি যেতে সক্ষম, যেহেতু সেগুলি থেকেই উদ্ভূত DbContext
।
খারাপ দিকটি হ'ল আপনাকে DbContext
পদ্ধতি থেকে পদ্ধতিতে (যাকে বলা হয় মেথড ইনজেকশন) around মনে রাখবেন যে এক অর্থে এই সমাধানটি 'স্কোপড' পদ্ধতির সমান, তবে এখন সুযোগটি অ্যাপ্লিকেশন কোডটিতেই নিয়ন্ত্রণ করা হয় (এবং সম্ভবত বহুবার পুনরাবৃত্তি করা হয়)। এটি সেই অ্যাপ্লিকেশন যা কাজের ইউনিট তৈরি এবং নিষ্পত্তি করার জন্য দায়ী। যেহেতু DbContext
নির্ভরতা গ্রাফটি তৈরি হওয়ার পরে এটি তৈরি করা হয়েছে, কনস্ট্রাক্টর ইঞ্জেকশনটি চিত্রের বাইরে এবং যখন আপনাকে একটি শ্রেণি থেকে অন্য শ্রেণিতে প্রসঙ্গে যেতে হবে তখন আপনাকে মেথড ইনজেকশনটি মুলতবি করতে হবে।
পদ্ধতি ইনজেকশনটি তেমন খারাপ নয়, তবে ব্যবসায়ের যুক্তি আরও জটিল হয়ে উঠলে এবং আরও ক্লাস জড়িত হলে আপনাকে এটিকে পদ্ধতি থেকে পদ্ধতিতে এবং শ্রেণীতে শ্রেণিতে স্থান দিতে হবে, যা কোডকে অনেক জটিল করে তুলতে পারে (আমি দেখেছি) এটি অতীতে) একটি সহজ অ্যাপ্লিকেশন জন্য, এই পদ্ধতির ঠিক ঠিক করা হবে।
ডাউনসাইডগুলির কারণে, এই কারখানার পদ্ধতির বৃহত্তর সিস্টেমগুলির জন্য রয়েছে, অন্য একটি পদ্ধতি কার্যকর হতে পারে এবং এটিই সেই জায়গা যেখানে আপনি ধারক বা অবকাঠামো কোড / সংমিশ্রণ রুটকে কাজের ইউনিট পরিচালনা করতে দেন। আপনার প্রশ্ন সম্পর্কে এটি স্টাইল।
ধারকটিকে এবং / অথবা অবকাঠামোটি এটি পরিচালনা করতে দেয়, আপনার অ্যাপ্লিকেশন কোডটি একটি ইউওডাব্লু ইভেন্ট তৈরি করতে (allyচ্ছিকভাবে) প্রতিশ্রুতিবদ্ধ এবং নিষ্পত্তি করে দূষিত হয় না যা ব্যবসায়ের যুক্তিটিকে সহজ এবং পরিষ্কার রাখে (কেবলমাত্র একটি একক দায়িত্ব)। এই পদ্ধতির সাথে কিছু অসুবিধা রয়েছে। উদাহরণস্বরূপ, আপনি কি প্রতিশ্রুতিবদ্ধ এবং উদাহরণটি নিষ্পত্তি করেছেন?
কাজের একটি ইউনিট নিষ্পত্তি ওয়েব অনুরোধের শেষে করা যেতে পারে। অনেক লোক, ভুলভাবে ধরে নিয়েছেন যে এটিও কাজের একক প্রতিশ্রুতিবদ্ধ করার জায়গা। যাইহোক, আবেদনের সেই মুহুর্তে, আপনি কেবল নির্ধারণ করতে পারবেন না যে কাজের ইউনিটটি আসলে প্রতিশ্রুতিবদ্ধ হওয়া উচিত। উদাহরণস্বরূপ যদি ব্যবসায়ের স্তর কোডটি একটি ব্যতিক্রম ছুঁড়ে ফেলেছে যা কলস্ট্যাকের চেয়ে বেশি ধরা পড়ে, আপনি অবশ্যই কমিট করতে চান না ।
আসল সমাধানটি আবার স্পষ্টভাবে কোনও ধরণের সুযোগকে পরিচালনা করার জন্য, তবে এবার এটি কম্পোজিশন রুটের অভ্যন্তরে করুন। কমান্ড / হ্যান্ডলার প্যাটার্নের পিছনে সমস্ত ব্যবসায়ের যুক্তি বর্জন করে , আপনি এমন একটি সজ্জনকারী লিখতে সক্ষম হবেন যা প্রতিটি কমান্ড হ্যান্ডলারের চারপাশে মোড়ানো যায় যা এটি করতে দেয়। উদাহরণ:
class TransactionalCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
readonly DbContext context;
readonly ICommandHandler<TCommand> decorated;
public TransactionCommandHandlerDecorator(
DbContext context,
ICommandHandler<TCommand> decorated)
{
this.context = context;
this.decorated = decorated;
}
public void Handle(TCommand command)
{
this.decorated.Handle(command);
context.SaveChanges();
}
}
এটি নিশ্চিত করে যে আপনার একবার এই পরিকাঠামো কোডটি লিখতে হবে। যে কোনও দৃ solid় ডিআই কনটেইনার আপনাকে এই জাতীয় ডেকরেটরকে ICommandHandler<T>
একটি সুসংগত পদ্ধতিতে সমস্ত প্রয়োগের চারপাশে মোড়কে কনফিগার করতে দেয় ।