এ সম্পর্কে অনেক কিছুই বলা যায়। আমাকে ফোকাস করতে AsEnumerableএবং AsQueryableউপায়টিতে উল্লেখ ToList()করতে দিন।
এই পদ্ধতিগুলি কী করে?
AsEnumerableএবং AsQueryableঢালাই বা রূপান্তর করতে IEnumerableবা IQueryableযথাক্রমে। আমি বলি castালাই বা কোনও কারণে রূপান্তর :
উত্স অবজেক্ট ইতিমধ্যে লক্ষ্য ইন্টারফেস প্রয়োগ করে, উত্স অবজেক্ট নিজেই ফিরে আসে তবে লক্ষ্য ইন্টারফেসে কাস্ট হয়। অন্য কথায়: টাইপটি পরিবর্তিত হয় না, তবে সংকলন-সময় টাইপ হয়।
যখন উত্স অবজেক্টটি লক্ষ্য ইন্টারফেসটি প্রয়োগ করে না, উত্স অবজেক্টটি এমন একটি সামগ্রীতে রূপান্তরিত হয় যা লক্ষ্য ইন্টারফেস প্রয়োগ করে। সুতরাং টাইপ এবং সংকলন-টাইপ উভয়ই পরিবর্তন করা হয়।
আমি এটি কিছু উদাহরণ দিয়ে দেখান। আমি এই সামান্য পদ্ধতিটি পেয়েছি যা সংকলন-সময়ের ধরণ এবং কোনও বস্তুর প্রকৃত প্রকারের প্রতিবেদন ( সৌজন্য জন জেন স্কিট ):
void ReportTypeProperties<T>(T obj)
{
Console.WriteLine("Compile-time type: {0}", typeof(T).Name);
Console.WriteLine("Actual type: {0}", obj.GetType().Name);
}
আসুন একটি নির্বিচারে লিনাক-টু-এসকিউএল চেষ্টা করি Table<T>, যা প্রয়োগ করে IQueryable:
ReportTypeProperties(context.Observations);
ReportTypeProperties(context.Observations.AsEnumerable());
ReportTypeProperties(context.Observations.AsQueryable());
ফলাফল:
Compile-time type: Table`1
Actual type: Table`1
Compile-time type: IEnumerable`1
Actual type: Table`1
Compile-time type: IQueryable`1
Actual type: Table`1
আপনি দেখতে পাচ্ছেন যে টেবিল শ্রেণি নিজেই সর্বদা ফিরে আসে তবে এর প্রতিনিধিত্ব পরিবর্তন হয়।
এখন একটি বস্তু যে কার্যকরী IEnumerable, না IQueryable:
var ints = new[] { 1, 2 };
ReportTypeProperties(ints);
ReportTypeProperties(ints.AsEnumerable());
ReportTypeProperties(ints.AsQueryable());
ফলাফলগুলো:
Compile-time type: Int32[]
Actual type: Int32[]
Compile-time type: IEnumerable`1
Actual type: Int32[]
Compile-time type: IQueryable`1
Actual type: EnumerableQuery`1
এটা আছে। AsQueryable()অ্যারেটিকে একটিতে রূপান্তরিত করেছে EnumerableQuery, যা " IEnumerable<T>একটি IQueryable<T>ডেটা উত্স হিসাবে সংগ্রহকে উপস্থাপন করে ।" (দুটিই MSDN)।
এর ব্যাবহার কি?
AsEnumerableযে কোনও IQueryableপ্রয়োগ থেকে লিনকিউতে অবজেক্টগুলিতে (এল 2 ও) স্যুইচ করার জন্য প্রায়শই ব্যবহৃত হয় , বেশিরভাগ কারণে যে প্রাক্তন L2O এর কার্যকারিতা সমর্থন করে না। আরও তথ্যের জন্য দেখুন একটি লিনকিউ সত্তায় AsEnumerable () এর প্রভাব কী? ।
উদাহরণস্বরূপ, একটি সত্ত্বা ফ্রেমওয়ার্ক ক্যোয়ারিতে আমরা কেবলমাত্র একটি সীমিত সংখ্যক পদ্ধতি ব্যবহার করতে পারি। সুতরাং, উদাহরণস্বরূপ, যদি আমাদের কোনও ক্যোয়ারিতে আমাদের নিজস্ব পদ্ধতি ব্যবহার করতে হয় তবে আমরা সাধারণত কিছু লিখি
var query = context.Observations.Select(o => o.Id)
.AsEnumerable().Select(x => MySuperSmartMethod(x))
ToList - যা একটি পরিবর্তিত IEnumerable<T>একটি থেকে List<T>- প্রায়ই হিসাবে ভাল এই কাজের জন্য ব্যবহার করা হয়। AsEnumerableবনাম ব্যবহার করার সুবিধাটি ToListহ'ল ক্যোরিটি AsEnumerableকার্যকর করে না। AsEnumerableস্থগিত কার্যকরকরণ সংরক্ষণ করে এবং প্রায়শই অকেজো মধ্যবর্তী তালিকা তৈরি করে না।
অন্যদিকে, যখন একটি লিনকিউ ক্যোয়ারির জোরপূর্বক মৃত্যুদণ্ড কার্যকর করা হয়, ToListতা করার উপায় হতে পারে।
AsQueryableএকটি লভ্য সংগ্রহটি লিনকিউ বিবৃতিতে অভিব্যক্তি গ্রহণ করতে ব্যবহৃত হতে পারে। আরও বিশদের জন্য এখানে দেখুন: সংগ্রহের জন্য আমার কি সত্যই কি এসকিউয়ারেবল () ব্যবহার করা দরকার? ।
পদার্থের অপব্যবহারের উপর নোট!
AsEnumerableড্রাগ হিসাবে কাজ করে। এটি একটি দ্রুত সমাধান, তবে ব্যয় এবং এটি অন্তর্নিহিত সমস্যাটির সমাধান করে না।
অনেকগুলি স্ট্যাক ওভারফ্লো জবাবগুলিতে, আমি AsEnumerableলোকগুলি লিনকিউ এক্সপ্রেশনগুলিতে অসমর্থিত পদ্ধতিগুলির সাথে যে কোনও সমস্যা সমাধানের জন্য আবেদন করতে দেখি । তবে দাম সবসময় পরিষ্কার হয় না। উদাহরণস্বরূপ, আপনি যদি এটি করেন:
context.MyLongWideTable // A table with many records and columns
.Where(x => x.Type == "type")
.Select(x => new { x.Name, x.CreateDate })
... সমস্ত কিছু ঝরঝরে করে একটি এসকিউএল বিবৃতিতে অনুবাদ করা হয়েছে যা ফিল্টার ( Where) এবং প্রকল্পগুলি ( Select)। অর্থাৎ এসকিউএল ফলাফলের সেটের যথাক্রমে দৈর্ঘ্য এবং প্রস্থ উভয়ই হ্রাস পেয়েছে।
এখন ধরুন ব্যবহারকারীরা কেবল তারিখের অংশটি দেখতে চান CreateDate। সত্তা ফ্রেমওয়ার্কে আপনি তা দ্রুত আবিষ্কার করতে পারবেন ...
.Select(x => new { x.Name, x.CreateDate.Date })
... সমর্থিত নয় (লেখার সময়)। আহ, ভাগ্যক্রমে AsEnumerableঠিক আছে:
context.MyLongWideTable.AsEnumerable()
.Where(x => x.Type == "type")
.Select(x => new { x.Name, x.CreateDate.Date })
অবশ্যই, এটি চলমান, সম্ভবত। তবে এটি পুরো টেবিলটিকে মেমরির মধ্যে টান দেয় এবং তারপরে ফিল্টার এবং অনুমানগুলি প্রয়োগ করে। ভাল, বেশিরভাগ লোক Whereপ্রথমটি করার মতো যথেষ্ট স্মার্ট :
context.MyLongWideTable
.Where(x => x.Type == "type").AsEnumerable()
.Select(x => new { x.Name, x.CreateDate.Date })
তবে তবুও সমস্ত কলামগুলি প্রথমে আনা হয় এবং প্রজেকশনটি মেমোরিতে সম্পন্ন হয়।
আসল ফিক্সটি হ'ল:
context.MyLongWideTable
.Where(x => x.Type == "type")
.Select(x => new { x.Name, DbFunctions.TruncateTime(x.CreateDate) })
(তবে এর জন্য আরও কিছুটা বেশি জ্ঞান প্রয়োজন ...)
এই পদ্ধতিগুলি কী করে না?
আইকোয়ারিযোগ্য ক্ষমতা পুনরুদ্ধার করুন
এখন একটি গুরুত্বপূর্ণ সতর্কতা। যখন তুমি কর
context.Observations.AsEnumerable()
.AsQueryable()
আপনি উত্স অবজেক্ট হিসাবে উপস্থাপন শেষ হবে IQueryable। (কারণ উভয় পদ্ধতিই কেবল কাস্ট করে এবং রূপান্তর করে না)।
তবে আপনি যখন করবেন
context.Observations.AsEnumerable().Select(x => x)
.AsQueryable()
ফলাফল কি হবে?
Selectএকটি উত্পাদন করে WhereSelectEnumerableIterator। এটি একটি অভ্যন্তরীণ। নেট ক্লাস যা প্রয়োগ করে IEnumerable, নাIQueryable । সুতরাং অন্য ধরণের রূপান্তর ঘটেছে এবং পরবর্তীকালে AsQueryableআর কখনও আসল উত্সটি ফিরে আসতে পারে না।
এর নিদর্শনটি হ'ল ব্যবহার AsQueryableকরা কোনও ক্যোয়ার সরবরাহকারীকে তার নির্দিষ্ট বৈশিষ্ট্য সহ একটি গণনাযোগ্য হিসাবে ইনজেক্ট করার উপায় নয় । ধরুন আপনি করেন
var query = context.Observations.Select(o => o.Id)
.AsEnumerable().Select(x => x.ToString())
.AsQueryable()
.Where(...)
শর্তটি কখনই এসকিউএল তে অনুবাদ করা হবে না। AsEnumerable()লিনকিউ বিবৃতি অনুসরণ করার পরে সত্তা ফ্রেমওয়ার্ক ক্যোয়ারী সরবরাহকারীর সাথে সংযোগটি স্থির করে দেয়।
আমি ইচ্ছাকৃতভাবে এই উদাহরণটি দেখাই কারণ আমি এখানে এমন প্রশ্ন দেখেছি যেখানে লোকেরা Includeকল করে কোনও সংকলনে দক্ষতার জন্য 'ইনজেক্ট' করার চেষ্টা করে AsQueryable। এটি সংকলন করে চালিত হয় তবে এটি কিছুই করে না কারণ অন্তর্নিহিত অবজেক্টটির Includeআর বাস্তবায়ন নেই।
এক্সিকিউট
উভয়ই AsQueryableএবং উত্স অবজেক্টটি AsEnumerableকার্যকর (বা গণ্য ) করবেন না । তারা কেবল তাদের ধরণ বা উপস্থাপনা পরিবর্তন করে। উভয় জড়িত ইন্টারফেস, IQueryableএবং IEnumerable, "ঘটতে অপেক্ষা একটি গণনা" ছাড়া আর কিছুই নয়। বাধ্য হয়ে তারা তা করার আগে তাদের মৃত্যুদণ্ড কার্যকর করা হয় না, উদাহরণস্বরূপ, উপরে বর্ণিত হিসাবে, কল করে ToList()।
এর অর্থ হ'ল কোনও বস্তুকে IEnumerableডেকে একটি প্রাপ্ত সম্পাদন করাই অন্তর্নিহিত কার্য সম্পাদন করবে । উইলের পরবর্তী ক্রিয়াকলাপ আবার কার্যকর করে । যা খুব ব্যয়বহুল হতে পারে।AsEnumerableIQueryableIQueryableIEnumerableIQueryable
নির্দিষ্ট বাস্তবায়ন
এখনও অবধি, এটি কেবলমাত্র Queryable.AsQueryableএবং Enumerable.AsEnumerableসম্প্রসারণ পদ্ধতি সম্পর্কে ছিল । তবে অবশ্যই যে কেউ একই নামগুলি (এবং ফাংশন) সহ উদাহরণ পদ্ধতি বা এক্সটেনশন পদ্ধতি লিখতে পারেন।
আসলে, একটি নির্দিষ্ট AsEnumerableএক্সটেনশন পদ্ধতির একটি সাধারণ উদাহরণ DataTableExtensions.AsEnumerable। DataTableপ্রয়োগ করে না IQueryableবা IEnumerable, তাই নিয়মিত বর্ধনের পদ্ধতি প্রয়োগ হয় না।