আপনার কন্ট্রোলারে এসকিউএল এড়ানোর কৌশলগুলি… বা আমার মডেলগুলিতে আমার কতগুলি পদ্ধতি থাকা উচিত?


17

সুতরাং আমি যে পরিস্থিতিটি প্রায়শই সংঘটিত হয়ে থাকি তা হ'ল আমার মডেলগুলি আরম্ভ হয়:

  • টন এবং টন পদ্ধতি সহ দানবগুলিতে বৃদ্ধি করুন

অথবা

  • আপনাকে তাদের কাছে এসকিউএল এর টুকরো পাস করার অনুমতি দিন, যাতে তারা এক মিলিয়ন বিভিন্ন পদ্ধতির প্রয়োজন না হয়ে যথেষ্ট নমনীয় হয়

উদাহরণস্বরূপ, বলুন আমাদের একটি "উইজেট" মডেল রয়েছে। আমরা কয়েকটি প্রাথমিক পদ্ধতি দিয়ে শুরু করি:

  • পেতে ($ ID)
  • সন্নিবেশ ($ রেকর্ড)
  • আপডেট (আইডি, $ রেকর্ড)
  • ডিলিট ($ ID)
  • getList () // উইজেটগুলির একটি তালিকা পান

এগুলি সব ঠিকঠাক এবং ঘৃণ্য, তবে তারপরে আমাদের কিছু প্রতিবেদন দরকার:

  • listCreatedBetween ($ start_date, $ end_date)
  • তালিকাপরিচালিত মধ্যে ((স্টার্ট_ডেট, $ শেষ_ তারিখ)
  • listOfPending ()

এবং তারপরে রিপোর্টিং জটিল হতে শুরু করে:

  • listPendCreatedBetween ($ start_date, $ end_date)
  • listForCustomer ($ গ্রাহক)
  • listPendCreatedBetweenForCustomer ($ গ্রাহক_আইডি, $ শুরু_ তারিখ, $ শেষ_ তারিখ)

আপনি দেখতে পাচ্ছেন যে এটি কোথায় বৃদ্ধি পাচ্ছে ... অবশেষে আমাদের অনেকগুলি নির্দিষ্ট ক্যোয়ারী প্রয়োজনীয়তা রয়েছে যা আমাকে হয় টন এবং টন পদ্ধতি প্রয়োগ করতে হবে, বা কোনও ধরণের "কোয়েরি" অবজেক্ট যা আমি একক -> ক্যোয়ারিতে যেতে পারি (কোয়েরি) $ প্রশ্ন) পদ্ধতি ...

... বা কেবল বুলেট কামড়ান, এবং এই জাতীয় কিছু শুরু করুন:

  • তালিকা = মাইমোডেল-> ক্যোয়ারী ("শুরু_ তারিখ> এক্স এবং শেষ_ তারিখ <ওয়াই এবং মুলতুবি = 1 এবং গ্রাহক_আইডি = জেড")

আরও 50 মিলিয়ন অন্যান্য নির্দিষ্ট পদ্ধতির পরিবর্তে এর মতো একটি পদ্ধতি রাখার জন্য একটি নির্দিষ্ট আবেদন রয়েছে ... তবে এটি কখনও কখনও নিয়ন্ত্রকের মধ্যে মূলত এসকিউএল কী আছে তার একটি গাদা স্টাফ করতে "ভুল" বোধ করে।

এরকম পরিস্থিতি পরিচালনা করার জন্য কি কোনও "সঠিক" উপায় আছে? জেনেরিক -> ক্যোয়ারী () পদ্ধতিতে এর মতো স্টাফিং কোয়েরি করা কি গ্রহণযোগ্য বলে মনে হচ্ছে?

আরও ভাল কৌশল আছে?


আমি এখনই একই সমস্যাটি অ-এমভিসি প্রকল্পে যাচ্ছি। প্রশ্নটি উঠে আসে যে ডেটা অ্যাক্সেস লেয়ারটি প্রতিটি সঞ্চিত প্রক্রিয়াটি বিমূর্ত করা উচিত এবং ব্যবসার লজিক লেয়ার ডাটাবেস অজ্ঞেয়বাদী ছেড়ে দেওয়া উচিত, বা ডেটা অ্যাক্সেস স্তরটি অন্তর্নিহিত ডাটাবেস সম্পর্কে কিছু জেনে ব্যবসায়ের স্তরটির ব্যয় করে জেনেরিক হওয়া উচিত? সম্ভবত একটি মধ্যবর্তী সমাধান হ'ল এক্সিকিউটিএসপি (স্ট্রিং স্প্যানাম, প্যারাম অবজেক্ট [] প্যারামিটার) এর মতো কিছু থাকে, তারপরে ব্যবসায়ের স্তরটি পড়ার জন্য একটি কনফিগার ফাইলে সমস্ত এসপি নাম অন্তর্ভুক্ত করে। যদিও এর সত্যিকার অর্থে আমার খুব ভালো উত্তর নেই।
গ্রেগ জ্যাকসন

উত্তর:


10

এন্টারপ্রাইজ অ্যাপ্লিকেশন আর্কিটেকচারের মার্টিন ফাউলারের প্যাটার্নস ক্যোয়ারী অবজেক্টের ব্যবহার সহ বেশ কয়েকটি ওআরএম সম্পর্কিত প্যাটার্নগুলি বর্ণনা করে, যা আমি পরামর্শ দিই।

ক্যোয়ারী অবজেক্টগুলি প্রতিটি প্রশ্নের জন্য যুক্তি আলাদাভাবে পরিচালিত এবং রক্ষণাবেক্ষণ কৌশল অবজেক্টগুলিতে আলাদা করে একক দায়িত্বের নীতি অনুসরণ করতে দেয়। হয় আপনার নিয়ামক সরাসরি তাদের ব্যবহার পরিচালনা করতে পারেন, বা এটি একটি গৌণ নিয়ামক বা সহায়তাকারী বস্তুর কাছে অর্পণ করতে পারেন।

আপনি তাদের অনেক হবে? অবশ্যই. কিছু জেনেরিক প্রশ্নের মধ্যে গ্রুপ করা যেতে পারে? হ্যাঁ আবার।

আপনি মেটাডেটা থেকে অবজেক্ট তৈরি করতে নির্ভরতা ইনজেকশন ব্যবহার করতে পারেন? বেশিরভাগ ওআরএম সরঞ্জাম এটি করে।


4

এটি করার কোনও সঠিক উপায় নেই। সমস্ত জটিলতা বিমূর্ত করতে অনেকে ORM ব্যবহার করেন। আরও উন্নত কিছু ORMs কোড এক্সপ্রেশনগুলিকে জটিল এসকিউএল স্টেটমেন্টগুলিতে অনুবাদ করে। ওআরএমগুলির পাশাপাশি তাদের ডাউনসাইডও রয়েছে, তবে অনেক অ্যাপ্লিকেশনের জন্য বেনিফিটগুলি ব্যয়কে ছাড়িয়ে যায়।

আপনি যদি কোনও বিশাল ডেটাসেটের সাথে কাজ না করে থাকেন তবে সবচেয়ে সহজ কাজটি হ'ল সম্পূর্ণ টেবিলটি মেমোরিতে নির্বাচন করা এবং কোডে ফিল্টার করা।

//pseudocode
List<Person> people = Sql.GetList<Person>("select * from people");
List<Person> over21 = people.Where(x => x.Age >= 21);

অভ্যন্তরীণ প্রতিবেদনের অ্যাপ্লিকেশনগুলির জন্য এই পদ্ধতিটি সম্ভবত ভাল। যদি ডেটাসেটটি সত্যিই বড় হয় তবে আপনার টেবিলটিতে প্রচুর কাস্টম পদ্ধতি এবং যথাযথ সূচকের প্রয়োজন শুরু হবে।


1
"এটি করার কোনও সঠিক উপায় নেই" এর জন্য + 1
ওজ

1
দুর্ভাগ্যক্রমে, ডেটা সেটের বাইরে ফিল্টারিং করা আমাদের পক্ষে কাজ করা সবচেয়ে ক্ষুদ্রতম ডেটা সেট সহ আসলেই কোনও বিকল্প নয় it's এটি কেবল খুব ধীর। :-( অন্যরা আমার একই সমস্যার মধ্যে পড়ে বলে শুনে ভাল লাগছে যদিও: :-)
কীথ পামার জুনিয়র

@ কিথপালমার কৌতূহলের বাইরে, আপনার টেবিলগুলি কত বড়?
ড্যান

কয়েক হাজার না থাকলে কয়েক হাজার সারি। ডাটাবেসের বাইরে গ্রহণযোগ্য পারফরম্যান্স সহ ফিল্টার করার জন্য অনেকগুলি, ESPECIALLY as একটি বিতরিত আর্কিটেকচার যেখানে ডাটাবেসগুলি অ্যাপ্লিকেশনটির মতো একই মেশিনে নেই।
কীথ পামার জুনিয়র

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

4

কিছু ওআরএম আপনাকে প্রাথমিক পদ্ধতিগুলি থেকে শুরু করে জটিল ক্যোয়ারী তৈরির অনুমতি দেয়। এই ক্ষেত্রে

old_purchases = (Purchase.objects
    .filter(date__lt=date.today(),type=Purchase.PRESENT).
    .excude(status=Purchase.REJECTED)
    .order_by('customer'))

এর মধ্যে একটি সম্পূর্ণ বৈধ ক্যোয়ারী জ্যাঙ্গো ওআরএম-এর

ধারণাটি হ'ল আপনার কাছে কিছু ক্যোয়ারী বিল্ডার রয়েছে (এই ক্ষেত্রে Purchase.objects) যার অভ্যন্তরীণ স্থিতি কোয়েরি সম্পর্কিত তথ্য উপস্থাপন করে। মত পদ্ধতি get, filter, exclude, order_byবৈধ এবং আপডেট হওয়া স্থিতির সঙ্গে একটি নতুন কোয়েরি রচয়িতা ফিরে যান। এই অবজেক্টগুলি একটি পুনরাবৃত্ত ইন্টারফেস বাস্তবায়ন করে, যাতে আপনি যখন তাদের উপর পুনরাবৃত্তি করেন তখন ক্যোরিটি সম্পাদিত হয় এবং আপনি এখনও অবধি নির্মিত ক্যোয়ারির ফলাফলগুলি পান get যদিও এই উদাহরণটি জাঙ্গো থেকে নেওয়া হয়েছে, আপনি অন্য অনেকগুলি ওআরএম-তে একই কাঠামো দেখতে পাবেন।


পুরানো_পরিচাগুলি = ক্রয়.কমের ("তারিখ> তারিখ.আজ আজ () এবং টাইপ = ক্রয়.প্রিজেন্ট এবং স্থিতি! = ক্রয়.আরজেটড") এর মতো কোনও কিছুর চেয়ে এর কী কী সুবিধা হবে তা আমি দেখতে পাচ্ছি না; আপনি কেবল এসকিউএল আন্ডারস এবং ওআরএসকে পদ্ধতি অ্যান্ডস এবং ওআরগুলিতে তৈরি করে জটিলতা হ্রাস বা কিছু বিমূর্ত করছেন না- আপনি কেবল এএনএস এবং ওআর এর উপস্থাপনা পরিবর্তন করছেন, তাই না?
কীথ পামার জুনিয়র

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

2
... সর্বাধিক নির্দিষ্ট কেস। একটি সাধারণ উদাহরণ জ্যাঙ্গোর মডেলগুলির জন্য একটি ডিফল্ট ক্রম সংজ্ঞায়িত করছে। সমস্ত কোয়েরির ফলাফলগুলি যদি আপনি অন্যথায় নির্দিষ্ট না করেন তবে সেই ক্রম অনুসরণ করবে। চতুর্থত, পারফরম্যান্স কারণে আপনার যদি কখনও ডেটাটিকে অস্বীকৃতি জানাতে প্রয়োজন হয় তবে আপনার সমস্ত প্রশ্নের পুনর্লিখন না করে আপনাকে কেবল ওআরএমটি টুইঙ্ক করতে হবে।
Andrea

+1 যেমন উল্লিখিত, এবং লিনকিউর মতো গতিময় ক্যোয়ারী ভাষার জন্য।
ইভান প্লেস

2

একটি তৃতীয় পদ্ধতির আছে।

আপনার নির্দিষ্ট উদাহরণটি প্রয়োজনীয় বৈশিষ্ট্যগুলির সংখ্যা বাড়ার সাথে সাথে প্রয়োজনীয় পদ্ধতির সংখ্যায় তাত্পর্যপূর্ণ বৃদ্ধি দেখায়: আমরা প্রতিটি ক্যোয়ারী বৈশিষ্ট্যকে একত্রিত করে উন্নত ক্যোয়ারী সরবরাহ করার দক্ষতা চাই ... আমরা যদি পদ্ধতিগুলি যোগ করে এটি করি তবে আমাদের জন্য একটি পদ্ধতি রয়েছে বেসিক ক্যোয়ারী, দুটি আমরা যদি একটি optionচ্ছিক বৈশিষ্ট্য যুক্ত করি, চারটি আমরা দুটি যোগ করি, আটটি যোগ করলে তিনটি, 2 ^ n আমরা যদি বৈশিষ্ট্যগুলি যোগ করি তবে 2

এটি স্পষ্টতই তিন বা চারটি বৈশিষ্ট্যের বাইরে অপরিবর্তনীয়, এবং অনেকগুলি ঘনিষ্ঠভাবে সম্পর্কিত কোডের ঘ্রাণ এটি প্রায় পদ্ধতির মধ্যে অনুলিপি-পেস্ট করা হয়েছে।

প্যারামিটারগুলি ধরে রাখতে কোনও ডেটা অবজেক্ট যুক্ত করে আপনি এড়াতে পারেন এবং এমন একটি পদ্ধতি রয়েছে যা সরবরাহিত পরামিতিগুলির সেট (বা সরবরাহিত নয়) এর ভিত্তিতে কোয়েরি তৈরি করে। সেক্ষেত্রে একটি নতুন বৈশিষ্ট্য যেমন তারিখের সীমা যুক্ত করা আপনার ডেটা অবজেক্টে তারিখের জন্য সেটটার এবং গেটার যুক্ত করার মতো সহজ এবং তারপরে প্যারামিটারাইজড কোয়েরিটি তৈরি করা হয়েছে এমন একটি কোডের যোগ করুন:

if (dataObject.getStartDate() != null) {
    query += " AND (date BETWEEN ? AND ?) "
}

... এবং যেখানে প্যারামিটারগুলি কোয়েরিতে যুক্ত করা হয়েছে:

if (dataObject.getStartDate() != null) {
    preparedStatement.setTime(dataObject.getStartDate());
    preparedStatement.setTime(dataObject.getEndDate());
}

এই পদ্ধতিটি স্বেচ্ছাসেবী, অপরিকল্পিত প্রশ্নের সমাধান না করে বৈশিষ্ট্যগুলি যুক্ত করা হিসাবে রৈখিক কোড বৃদ্ধির অনুমতি দেয়।


0

আমি মনে করি এমভিসিতে আপনার মডেলগুলিতে যথাসম্ভব ডেটা অ্যাক্সেস রাখা সাধারণ sensকমত্য। অন্য ডিজাইনের প্রিসপিলগুলির মধ্যে একটি হ'ল আপনার আরও জেনেরিক প্রশ্নগুলির মধ্যে কিছু (যা আপনার মডেলের সাথে সরাসরি সম্পর্কিত নয়) একটি উচ্চতর, আরও বিমূর্ত স্তরে চলে যায় যেখানে আপনি অন্যান্য মডেলগুলিও এটি ব্যবহার করতে পারবেন। (আরআর তে, আমাদের ফ্রেমওয়ার্ক বলে কিছু রয়েছে) আপনার আরও একটি বিষয় বিবেচনা করতে হবে এবং তা হ'ল আপনার কোডটির রক্ষণাবেক্ষণযোগ্যতা। আপনার প্রকল্পটি বাড়ার সাথে সাথে, আপনার কাছে যদি কন্ট্রোলারগুলিতে ডেটা অ্যাক্সেস থাকে তবে এটি ট্র্যাক করা আরও ক্রমশ কঠিন হয়ে উঠবে (বর্তমানে আমরা একটি বিশাল প্রকল্পে এই সমস্যার মুখোমুখি হয়েছি) মডেলগুলি, যদিও পদ্ধতিগুলির সাথে বিশৃঙ্খলাবদ্ধ যে কোনও নিয়ন্ত্রণকারীর জন্য একক বিন্দু সরবরাহ করে যিনি টেবিলগুলি থেকে কোয়েরি শেষ হতে পারে। (এটি কোডের পুনঃব্যবহারের দিকেও ঝুঁকতে পারে যা ঘুরেফিরে উপকারী)


1
আপনি যার কথা বলছেন তার উদাহরণ ...?
কীথ পামার জুনিয়র 11

0

আপনার পরিষেবা স্তর ইন্টারফেসে অনেকগুলি পদ্ধতি থাকতে পারে তবে ডাটাবেসে কল করার একটি মাত্র থাকতে পারে।

একটি ডাটাবেসে 4 টি বড় অপারেশন রয়েছে

  • সন্নিবেশ
  • হালনাগাদ
  • মুছে ফেলা
  • প্রশ্ন

আর একটি .চ্ছিক পদ্ধতি হ'ল কিছু ডাটাবেস ক্রিয়াকলাপ চালানো যা প্রাথমিক ডিবি ক্রিয়াকলাপের আওতায় পড়ে না। আসুন যে এক্সিকিউট কল।

সন্নিবেশ এবং আপডেটগুলি এক অপারেশনে একত্রিত করা যায়, সেভ নামে পরিচিত।

আপনার পদ্ধতিগুলির অনেকগুলি কোয়েরির। তাই আপনি বেশিরভাগ তাত্ক্ষণিক চাহিদা পূরণের জন্য একটি জেনেরিক ইন্টারফেস তৈরি করতে পারেন। এখানে একটি নমুনা জেনেরিক ইন্টারফেস:

 public interface IDALService
    {
        DataTransferObject<T> Save<T>(DataTransferObject<T> Dto) where T : IPOCO;
        DataTransferObject<T> Search<T>(DataTransferObject<T> Dto) where T: IPOCO;
        DataTransferObject<T> Delete<T>(DataTransferObject<T> Dto) where T : IPOCO;
        DataTransferObject<T> Execute<T>(DataTransferObject<T> Dto) where T : IPOCO;
    }

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

সুতরাং, আপনার ক্ষেত্রে উইজেট রয়েছে। উইজেটগুলি আইপোকো ইন্টারফেস বাস্তবায়ন করবে।

সুতরাং, আপনার পরিষেবা স্তর মডেল হবে getList().

হাতল tranforming করার জন্য একটি ম্যাপিং স্তর হবে getListমধ্যে

Search<Widget>(DataTransferObject<Widget> Dto)

এবং বিপরীতভাবে. অন্যরা যেমন উল্লেখ করেছে, কোনও কোনও সময় এটি একটি ওআরএম এর মাধ্যমে করা হয় তবে শেষ পর্যন্ত আপনি প্রচুর বয়লারপ্লেট ধরণের কোড দিয়ে শেষ করেন, বিশেষত আপনার যদি 100 টি টেবিল থাকে। ORM জাদুকরভাবে প্যারামিটেড এসকিউএল তৈরি করে এবং এটি ডাটাবেসের বিপরীতে চালায়। যদি আপনার নিজের ঘূর্ণায়মান হয় তবে অতিরিক্তভাবে ডেটা স্তর নিজেই, এসপি, লিনক ইত্যাদি সেটআপ করার জন্য ম্যাপারগুলির প্রয়োজন হবে (মূলত ডেটাবেজে স্ক্যালএল যাওয়া)।

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

সুতরাং, মৌলিক কৌশলটি হ'ল:

  • পরিষেবা স্তর কল
  • কোনও ধরণের সংগ্রহস্থল / ম্যাপিং ব্যবহার করে সার্ভিস লেয়ারকে ডেটাবেসে কল করুন
  • ডাটাবেস কল

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

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