আইকনামেবল <T> বনাম আইকোয়্যারেবল <T> ফিরে আসছেন


1084

ফিরতি IQueryable<T>বনামের মধ্যে পার্থক্য কী IEnumerable<T>, কখন একজনের অপরটির চেয়ে বেশি পছন্দ করা উচিত?

IQueryable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

IEnumerable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

উত্তর:


1778

হ্যাঁ, উভয়ই আপনাকে মুলতুবি কার্যকর করতে হবে ।

পার্থক্যটি হ'ল IQueryable<T>লিনক-টু-এসকিউএল (লিংক-টু-টু-সত্যিই কিছু) কাজ করতে দেয় এমন ইন্টারফেস। সুতরাং আপনি যদি আপনার ক্যোয়ারিকে আরও একটি পরিমার্জন করেন তবে IQueryable<T>সেই প্রশ্নটি সম্ভব হলে ডাটাবেসে কার্যকর করা হবে।

জন্য IEnumerable<T>মামলা, এটা LINQ-টু-বস্তুর হতে হবে, যার মানে হল মূল প্রশ্নের সাথে মিলে সমস্ত বস্তু ডাটাবেস থেকে মেমরিতে লোড করা হবে।

কোডে:

IQueryable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

এই কোডটি কেবলমাত্র সোনার গ্রাহক নির্বাচন করতে এসকিউএল কার্যকর করবে exec অন্যদিকে, নীচের কোডটি ডাটাবেসে মূল ক্যোয়ারী কার্যকর করবে, তারপরে মেমরিতে নন-সোনার গ্রাহকদের ফিল্টার করবে:

IEnumerable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

এটি বেশ গুরুত্বপূর্ণ একটি পার্থক্য, এবং IQueryable<T>অনেক ক্ষেত্রেই কাজ করা আপনাকে ডাটাবেস থেকে অনেকগুলি সারি ফেরত থেকে বাঁচায়। আর একটি প্রধান উদাহরণটি হচ্ছে পেজিং করা: আপনি যদি ব্যবহার করেন Takeএবং Skipচালিয়ে যান তবে IQueryableআপনি কেবল অনুরোধ করা সারিগুলির সংখ্যা পাবেন; এটি একটি IEnumerable<T>করলে তা আপনার সমস্ত সারি স্মৃতিতে লোড হয়ে যায়।


32
দুর্দান্ত ব্যাখ্যা। এমন কি এমন কোনও পরিস্থিতি রয়েছে যেখানে আইক্যুয়্যারেবলের চেয়ে আইনমুনেবল ভাল?
fjxx

8
সুতরাং আমরা বলতে পারি যে আমরা যদি মেমোরি অবজেক্টটি ক্যোয়ারী করার জন্য আইকিউয়েরেবল ব্যবহার করি, তবে তারা আইনাম্যারেবল এবং আইকুয়েরেবলের মধ্যে কোনও তফাত হবে না?
তারিক

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

48
@fjxx হ্যাঁ আপনি যদি নিজের আসল ফলাফলটিতে বারবার ফিল্টার করতে চান (বেশ কয়েকটি শেষ ফলাফল)। আইকিউয়েরেবল ইন্টারফেসে এটি করা ডাটাবেসে একাধিক রাউন্ডট্রিপ তৈরি করবে, যেখানে আইনামিউরেবলের সাথে এটি করা মেমরির মধ্যে ফিল্টারিং করবে, এটি দ্রুততর করে তোলে (যতক্ষণ না ডেটার পরিমাণ পরিমাণে বিশাল না হয়)
পার হর্নশেজ-শোয়ারবেক

34
পছন্দ IEnumerableকরার আরেকটি কারণ IQueryableহ'ল সমস্ত লিনকিউ অপারেশনগুলি সমস্ত লিনকিউ সরবরাহকারীরা সমর্থন করে না। আপনি যতক্ষণ জানেন যে আপনি কী করছেন, আপনি IQueryableযতটা ক্যোয়ারীটি LINQ সরবরাহকারীর (লাইনকিউ 2 এসকিউএল, ইএফ, এনএইচবারনেট, মঙ্গোডিবি ইত্যাদির) কাছে চাপ দিতে পারেন। তবে আপনি যদি অন্য কোডটি আপনার সাথে যা করতে চান তা IQueryableশেষ পর্যন্ত আপনি সমস্যার মধ্যে পড়ে যাবেন কারণ কিছু ক্লায়েন্ট কোড কোথাও একটি অসমর্থিত অপারেশন ব্যবহার করেছে। আমি IQueryableসংগ্রহস্থল বা সমতুল্য স্তরের অতীতকে "বুনো" না ছড়িয়ে দেওয়ার পরামর্শের সাথে একমত ।
আভিশ

302

শীর্ষের উত্তরটি ভাল তবে এতে অভিব্যক্তি গাছগুলি উল্লেখ করা হয়নি যা দুটি ইন্টারফেসের পার্থক্য "কীভাবে" ব্যাখ্যা করে। মূলত, লিনকিউ এক্সটেনশনের দুটি অভিন্ন সেট রয়েছে। Where(), Sum(), Count(), FirstOrDefault()এক যে ফাংশন গ্রহণ এবং এক যে এক্সপ্রেশন স্বীকার করে:, ইত্যাদি সব দুটি সংস্করণ আছে।

  • IEnumerableসংস্করণ স্বাক্ষর হল:Where(Func<Customer, bool> predicate)

  • IQueryableসংস্করণ স্বাক্ষর হল:Where(Expression<Func<Customer, bool>> predicate)

আপনি সম্ভবত এটি উপলব্ধি না করেই উভয়কেই ব্যবহার করে আসছেন কারণ উভয়কেই অনুরূপ সিনট্যাক্স ব্যবহার করে ডাকা হয়:

যেমন Where(x => x.City == "<City>")উভয় IEnumerableএবং উপর কাজ করেIQueryable

  • Where()কোনও IEnumerableসংগ্রহ ব্যবহার করার সময় , সংকলক একটি সংকলিত ফাংশনটি পাস করেWhere()

  • Where()কোনও IQueryableসংগ্রহ ব্যবহার করার সময় , সংকলকটি একটি অভিব্যক্তি গাছকে পাস করে Where()। একটি এক্সপ্রেশন ট্রি প্রতিবিম্ব সিস্টেমের মতো তবে কোডের জন্য। সংকলকটি আপনার কোডটিকে একটি ডেটা স্ট্রাকচারে রূপান্তর করে যা আপনার কোডটি সহজে হজমযোগ্য এমন ফর্ম্যাটে কী করে তা বর্ণনা করে।

এই অভিব্যক্তি গাছ জিনিস কেন বিরক্ত? আমি কেবল Where()আমার ডেটা ফিল্টার করতে চাই । মূল কারণ হ'ল EF এবং লিনক 2 এসকিউএল ওআরএম উভয়ই এক্সপ্রেশন ট্রিগুলিকে সরাসরি এসকিউএলে রূপান্তর করতে পারে যেখানে আপনার কোডটি আরও দ্রুত কার্যকর করবে।

ওহ, এটি একটি নিখরচায় পারফরম্যান্স বৃদ্ধির মতো শোনাচ্ছে, আমি কি AsQueryable()সেই ক্ষেত্রে সমস্ত জায়গা ব্যবহার করব ? না, IQueryableকেবল তখনই কার্যকর যদি অন্তর্নিহিত ডেটা সরবরাহকারী এটি দিয়ে কিছু করতে পারে। একটি নিয়মিত ভালো কিছু রূপান্তর Listকরতে IQueryableযদি আপনার কোন উপকার দেবে না।


9
আইএমও এটি গৃহীত উত্তরের চেয়ে ভাল। তবে, আমি একটি জিনিস পাই না: আইকিউয়েরেবল নিয়মিত জিনিসগুলির জন্য কোনও সুবিধা দেয় না, ঠিক আছে, তবে এটি কোনওভাবেই খারাপ? কারণ যদি এটি কেবল কোনও সুবিধা না দেয় তবে এটি আইনামেবলকে পছন্দ করার পক্ষে পর্যাপ্ত কারণ নয়, তাই সমস্ত জায়গাতেই আইকুয়েরেবল ব্যবহারের ধারণাটি বৈধ থাকবে।
সের্গেই টেচেনভ

1
সের্গেই, আইকিউয়েরেবল আইয়ানম্যারেবল প্রসারিত করে তাই আইকিউয়েরেবল ব্যবহার করার সময় আপনি কোনও আইএনম্যারেবল ইনস্ট্যান্টেশন চেয়ে মেমরিতে আরও বেশি লোড করেন! সুতরাং এখানে একটি যুক্তি। ( স্ট্যাকওভারফ্লো / সেকশনস / ১২০64৮৮৮৮/২ সি ++ যদিও আমি ভেবেছিলাম আমি এটিকে প্রত্যাহার করতে পারি)
ভাইকিং

এটি সেরা উত্তর হওয়া সম্পর্কে সের্গেইয়ের সাথে একমত (যদিও স্বীকৃত উত্তরটি ঠিক আছে)। আমি যোগ করতে চাই যে আমার অভিজ্ঞতা, IQueryableনা পার্স ফাংশন হিসাবে ভাল আছে যেমন IEnumerableআছে: উদাহরণস্বরূপ, যদি আপনি জানেন যে যা উপাদান চান DBSet<BookEntity>একটি নেই List<BookObject>, dbSetObject.Where(e => !listObject.Any(o => o.bookEntitySource == e))একটি ব্যতিক্রম ছোঁড়ার: Expression of type 'BookEntity' cannot be used for parameter of type 'BookObject' of method 'Boolean Contains[BookObject] (IEnumerable[BookObject], BookObject)'। আমি .ToList()পরে যোগ করতে হবে dbSetObject
জিন-ডেভিড ল্যাঞ্জ

80

হ্যাঁ, উভয়ই মুলতুবি কার্যকর কার্যকর করেন। এসকিউএল সার্ভার প্রোফাইলার ব্যবহার করে পার্থক্যটি চিত্রিত করা যাক ....

যখন আমরা নিম্নলিখিত কোডটি চালাই:

MarketDevEntities db = new MarketDevEntities();

IEnumerable<WebLog> first = db.WebLogs;
var second = first.Where(c => c.DurationSeconds > 10);
var third = second.Where(c => c.WebLogID > 100);
var result = third.Where(c => c.EmailAddress.Length > 11);

Console.Write(result.First().UserName);

এসকিউএল সার্ভারের প্রোফাইলারে আমরা এর সমান একটি কমান্ড পাই:

"SELECT * FROM [dbo].[WebLog]"

ওয়েবলগ টেবিলের বিপরীতে কোডটির ব্লকটি চালাতে আনুমানিক 90 সেকেন্ড সময় লাগে যার 1 মিলিয়ন রেকর্ড রয়েছে।

সুতরাং, সমস্ত সারণী রেকর্ডগুলি বস্তু হিসাবে মেমরিতে লোড হয় এবং তারপরে প্রতিটি দিয়ে .যে কোথায় () এই বস্তুর বিরুদ্ধে মেমরির অন্য ফিল্টার হবে।

যখন আমরা উপরের উদাহরণের IQueryableপরিবর্তে IEnumerable(দ্বিতীয় লাইন) ব্যবহার করি:

এসকিউএল সার্ভারের প্রোফাইলারে আমরা এর সমান একটি কমান্ড পাই:

"SELECT TOP 1 * FROM [dbo].[WebLog] WHERE [DurationSeconds] > 10 AND [WebLogID] > 100 AND LEN([EmailAddress]) > 11"

কোডটি ব্যবহার করে এই ব্লকটি চালাতে প্রায় চার সেকেন্ড সময় লাগে IQueryable

আইকিউয়েরেবলের একটি সম্পত্তি রয়েছে Expressionযা একটি ট্রি এক্সপ্রেশন সংরক্ষণ করে যা তৈরি হতে শুরু করে যখন আমরা resultআমাদের উদাহরণটি ব্যবহার করি (যা পিছিয়ে দেওয়া কার্যকর বলা হয়), এবং শেষে এই এক্সপ্রেশনটি একটি এসকিউএল কোয়েরিতে রূপান্তরিত হবে ডাটাবেস ইঞ্জিনে চালানোর জন্য।


5
আইইনুমেবলে কাস্ট করার সময় এটি আমাকে শিখায়, অন্তর্নিহিত আইকিউয়েরেবল এটি আইকুয়েরেবল এক্সটেনশন পদ্ধতি হারিয়ে ফেলে।
Yiping

56

উভয়ই আপনাকে মুলতুবি কার্যকর করতে হবে, হ্যাঁ।

যেটির জন্য অন্যটির চেয়ে বেশি পছন্দ করা হয়, এটি আপনার অন্তর্নিহিত ডেটাসোর্সটি নির্ভর করে।

একটি ফেরত দেওয়া IEnumerableরানটাইমকে স্বয়ংক্রিয়ভাবে আপনার সংগ্রহটি জিজ্ঞাসা করতে অবজেক্টগুলিতে LINQ ব্যবহার করতে বাধ্য করবে।

কোনওটি IQueryable(যা প্রয়োগ করে IEnumerable, ফেরত দেওয়া ) আপনার ক্যোয়ারীটিকে এমন কোনও কিছুতে অনুবাদ করার জন্য অতিরিক্ত কার্যকারিতা সরবরাহ করে যা অন্তর্নিহিত উত্স (লিনকু থেকে এসকিউএল, লিনকু থেকে এক্সএমএল ইত্যাদি) আরও ভাল সম্পাদন করতে পারে।


30

সাধারণ পদে আমি নিম্নলিখিতগুলি সুপারিশ করব:

  • রিটার্ন IQueryable<T>আপনি আপনার পদ্ধতি ব্যবহার করে ক্যোয়ারী আপনি চালানোর আগে আসতে পরিমার্জন ডেভেলপার সক্রিয় করতে চান।

  • IEnumerableআপনি যদি গণনা করতে অবজেক্টের একটি সেট পরিবহন করতে চান তবে ফিরে যান।

IQueryableএটি কী হিসাবে তা কল্পনা করুন - ডেটার জন্য একটি "ক্যোয়ারী" (যা আপনি চাইলে পরিমার্জন করতে পারেন)। একটি IEnumerableহ'ল অবজেক্টের একটি সেট (যা ইতিমধ্যে প্রাপ্ত বা তৈরি করা হয়েছিল) যার উপরে আপনি গণনা করতে পারেন।


2
"গণনা করতে পারে," নয় "আইনিউমারেবল করতে পারে।"
কেসি

28

এর আগে অনেক কিছু বলা হয়েছিল, তবে আরও প্রযুক্তিগত উপায়ে শিকড়গুলিতে ফিরে:

  1. IEnumerable মেমরির অবজেক্টগুলির একটি সংকলন যা আপনি গণনা করতে পারেন - একটি মেমরির ক্রম যা এর মাধ্যমে পুনরাবৃত্তি করা সম্ভব করে তোলে ( foreachলুপের মধ্যে এটি সহজতর করে তোলে যদিও আপনি IEnumeratorকেবল সাথে যেতে পারেন )। তারা যেমন স্মৃতিতে থাকে।
  2. IQueryable চূড়ান্ত ফলাফলটি গণনা করার ক্ষমতা সহ এমন একটি অভিব্যক্তি গাছ যা কোনও সময়ে অন্য কোনও কিছুতে অনুবাদ হয়ে যায় । আমার ধারণা এটি বেশিরভাগ লোককেই বিভ্রান্ত করে।

তাদের স্পষ্টতই ভিন্ন ধারণা রয়েছে।

IQueryableএকটি এক্সপ্রেশন ট্রি (একটি ক্যোয়ারী, সহজভাবে) উপস্থাপন করে যা অন্তর্নিহিত ক্যোয়ার সরবরাহকারীর দ্বারা অন্য কোনও কিছুতে অনুবাদ করা হবে যেমন মুক্তির API গুলি বলা হবে, যেমন LINQ সমষ্টিগত ফাংশন (যোগফল, গণনা ইত্যাদি) বা টোললিস্ট [অ্যারে, অভিধান ,. ..]। এবং IQueryableঅবজেক্টগুলি প্রয়োগ করে IEnumerable, IEnumerable<T>যাতে তারা কোনও প্রশ্নের প্রতিনিধিত্ব করে তবে সেই ক্যোয়ারির ফলাফলটি পুনরাবৃত্তি হতে পারে। এর অর্থ হল আইকুয়েরেবলের জন্য কেবল অনুসন্ধান করা উচিত নয়। সঠিক শব্দটি হ'ল তারা হ'ল অভিব্যক্তি গাছ

এখন এই এক্সপ্রেশনগুলি কীভাবে কার্যকর করা হয় এবং তারা কী পরিবর্তন করে তা সমস্ত তথাকথিত ক্যোয়ারী সরবরাহকারী (এক্সপ্রেশন এক্সিকিউটররা আমরা তাদের ভাবতে পারি)।

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

সুতরাং মূলত, IQueryableঅবজেক্টগুলি পুরোপুরি দীর্ঘ অবধি নির্মিত হচ্ছে যতক্ষণ না আমরা স্পষ্টভাবে তাদের প্রকাশ করি এবং সিস্টেমকে এসকিউএল বা যে কোনও ক্ষেত্রে পুনরায় লেখার জন্য এবং প্রবাহের প্রক্রিয়াটির জন্য নির্বাহের শৃঙ্খলা প্রেরণ করতে না পারি।

যদি হিসাবে বিলম্বিত সঞ্চালনের এটি একটি এর LINQবৈশিষ্ট্য মেমরি অভিব্যক্তি গাছ প্রকল্প তুলে ধরুন এবং শুধুমাত্র চাহিদা, যখনই নির্দিষ্ট API গুলি ক্রম (একই কাউন্ট, ToList, ইত্যাদি) বিরুদ্ধে বলা হয় উপর সঞ্চালনের সেটিকে পাঠান।

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

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


3
আইএনমেবলেবলস সর্বদা স্মৃতিতে থাকা মন্তব্যটি খুব প্রয়োজনে সত্য নয়। আইকিউয়েরেবল ইন্টারফেস আইইনুমারেবল ইন্টারফেস প্রয়োগ করে। এর কারণে, আপনি একটি কাঁচা আইকিউয়ারেবল পাস করতে পারেন যা একটি লিনিকিউ-থেকে-এসকিউএল কোয়েরিটি উপস্থাপন করে এমন একটি দৃশ্যে যা একটি IEnumerable প্রত্যাশা করে! আপনার ডেটা প্রসঙ্গের মেয়াদ শেষ হয়ে গেছে বা আপনি MARS (একাধিক সক্রিয় ফলাফল সেট) নিয়ে ইস্যুগুলিতে চলে এসেছেন তা জানতে পেরে আপনি অবাক হতে পারেন।

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

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

24

সাধারণভাবে আপনি ক্যোয়ারের মূল স্থিতিশীল প্রকারটি সংরক্ষণ না করে অবধি সংরক্ষণ করতে চান until

এই কারণে, আপনি 'Var' পরিবর্তে উভয় হিসাবে আপনার পরিবর্তনশীল বর্ণনা করতে পারেন IQueryable<>বা IEnumerable<>আর তুমি জানবে যে আপনি টাইপ পরিবর্তন করা হয় না।

আপনি যদি কোনওটি দিয়ে শুরু করেন IQueryable<>, সাধারণত কোনও IQueryable<>পরিবর্তন করার কোনও বাধ্যতামূলক কারণ না পাওয়া পর্যন্ত আপনি সাধারণত এটি হিসাবে রাখতে চান । এর কারণ হ'ল আপনি ক্যোয়ারী প্রসেসরটিকে যথাসম্ভব তথ্য দিতে চান। উদাহরণস্বরূপ, আপনি যদি কেবলমাত্র 10 টি ফলাফল ব্যবহার করতে যাচ্ছেন (আপনি কল করেছেন Take(10)) তবে আপনি এসকিউএল সার্ভারকে সে সম্পর্কে জানতে চান যাতে এটি এর ক্যোয়ারী পরিকল্পনাগুলি অনুকূল করতে পারে এবং কেবলমাত্র আপনি যে ডেটা ব্যবহার করবেন তা প্রেরণ করতে পারে।

টাইপ পরিবর্তন করার জন্য একটি বাধ্যকারী কারণ থেকে IQueryable<>থেকে IEnumerable<>হতে পারে যে আপনার কিছু এক্সটেনশন ফাংশন যা বাস্তবায়ন আহ্বান করা হয় IQueryable<>আপনার নির্দিষ্ট বস্তু পারেন হ্যান্ডেল বা হ্যান্ডলগুলি করতে পারবে না inefficiently। সেক্ষেত্রে, আপনি টাইপটি রূপান্তর করতে চাইতে পারেন IEnumerable<>( টাইপের কোনও ভেরিয়েবলকে অর্পণ করে IEnumerable<>বা AsEnumerableউদাহরণস্বরূপ এক্সটেনশন পদ্ধতিটি ব্যবহার করে ) যাতে আপনি যে এক্সটেনশন ফাংশনগুলি কল করেন Enumerableক্লাসের পরিবর্তে ক্লাসে সেগুলি হয়ে যায় Queryable


18

এখানে সংক্ষিপ্ত উত্স কোড নমুনা সহ একটি ব্লগ পোস্ট রয়েছে যাতে কীভাবে অপব্যবহারের ফলে IEnumerable<T>নাটকীয়ভাবে লিনকিউ ক্যোয়ারী কার্যকারিতা প্রভাবিত করতে পারে: সত্তা ফ্রেমওয়ার্ক: আইকুয়েরেবল বনাম আইমনুমেবল

যদি আমরা আরও গভীর খনন করি এবং উত্সগুলিতে নজর রাখি তবে আমরা দেখতে পাই যে স্পষ্টতই বিভিন্ন এক্সটেনশন পদ্ধতিগুলি সুগন্ধযুক্ত IEnumerable<T>:

// Type: System.Linq.Enumerable
// Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll
public static class Enumerable
{
    public static IEnumerable<TSource> Where<TSource>(
        this IEnumerable<TSource> source, 
        Func<TSource, bool> predicate)
    {
        return (IEnumerable<TSource>) 
            new Enumerable.WhereEnumerableIterator<TSource>(source, predicate);
    }
}

এবং IQueryable<T>:

// Type: System.Linq.Queryable
// Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll
public static class Queryable
{
    public static IQueryable<TSource> Where<TSource>(
        this IQueryable<TSource> source, 
        Expression<Func<TSource, bool>> predicate)
    {
        return source.Provider.CreateQuery<TSource>(
            Expression.Call(
                null, 
                ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(
                    new Type[] { typeof(TSource) }), 
                    new Expression[] 
                        { source.Expression, Expression.Quote(predicate) }));
    }
}

প্রথমটি গণনাযোগ্য পুনরাবৃত্তি প্রদান করে, এবং দ্বিতীয়টি IQueryableউত্সে নির্দিষ্ট করা ক্যোয়ারী সরবরাহকারীর মাধ্যমে ক্যোয়ারী তৈরি করে ।


11

আমি সম্প্রতি IEnumerablev নিয়ে একটি ইস্যুতে দৌড়েছি IQueryable। ব্যবহৃত অ্যালগরিদম IQueryableফলাফলের সেট পাওয়ার জন্য প্রথমে একটি ক্যোয়ারী সম্পাদন করে । এরপরে foreachআইটেমগুলি সত্তা ফ্রেমওয়ার্ক (ইএফ) শ্রেণি হিসাবে ইনস্ট্যান্ট করে একটি লুপে পৌঁছে দেওয়া হয়েছিল । এই ইএফ ক্লাসটি তখন fromলিনাক টু সত্তা কোয়েরির ক্লজে ব্যবহৃত হত , যার ফলে ফলাফলটি হয়েছিল IEnumerable

আমি এজেন্সিগুলির জন্য ইএফ এবং লিনকের কাছে মোটামুটি নতুন, সুতরাং বাধাটি কী তা বুঝতে সময় লাগল। মিনিপ্রোফিলিং ব্যবহার করে, আমি কোয়েরিটি খুঁজে পেয়েছি এবং তারপরে স্বতন্ত্র ক্রিয়াকলাপগুলিকে একক IQueryableলিনকে সত্তা কোয়েরির জন্য রূপান্তর করেছি । এটি IEnumerableসম্পাদন করতে 15 সেকেন্ড এবং সময় IQueryableগ্রহণ করেছিল 0.5 সেকেন্ড। সেখানে তিনটি সারণী জড়িত ছিল এবং এটি পড়ার পরে, আমি বিশ্বাস করি যে IEnumerableক্যোয়ারীটি আসলে তিনটি টেবিল ক্রস-প্রোডাক্ট গঠন করেছিল এবং ফলাফলগুলি ফিল্টার করে।

আপনার পরিবর্তনগুলি পরিমাপযোগ্য করে তোলার জন্য আইকুয়ারিয়েলগুলিকে থাম্ব-র থাম্ব এবং আপনার কাজের প্রোফাইল হিসাবে ব্যবহার করার চেষ্টা করুন।


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

10

আপাতদৃষ্টিতে দ্বন্দ্বপূর্ণ প্রতিক্রিয়ার কারণে (বেশিরভাগই আশেপাশের)।

(1) ইন্টারফেস IQueryableপ্রসারিত IEnumerable। (আপনি IQueryableএমন কোনও কিছুতে প্রেরণ করতে পারেন যা IEnumerableত্রুটি ছাড়াই প্রত্যাশা করে ))

(২) ফলাফল সেটটি পুনরাবৃত্তি করার সময় উভয় IQueryableএবং IEnumerableলাইনকিউ অলস লোডিংয়ের চেষ্টা করে। (নোট করুন যে প্রয়োগটি প্রতিটি ধরণের জন্য ইন্টারফেস এক্সটেনশন পদ্ধতিতে দেখা যায় can)

অন্য কথায়, IEnumerablesএকচেটিয়াভাবে "ইন-মেমরি" নয়। IQueryablesডেটাবেজে সর্বদা কার্যকর করা হয় না। IEnumerableমেমরিতে জিনিসগুলি অবশ্যই লোড করা উচিত (একবার পুনরুদ্ধার করা, সম্ভবত অলসভাবে) কারণ এটির কোনও অ্যাবস্ট্রাক্ট ডেটা সরবরাহকারী নেই। IQueryablesকোনও বিমূর্ত সরবরাহকারীর উপর নির্ভর করুন (যেমন লিনকুই-টু এসকিউএল), যদিও এটি .NET ইন-মেমরি সরবরাহকারীও হতে পারে।

নমুনা ব্যবহার ক্ষেত্রে

(ক) IQueryableEF প্রসঙ্গে রেকর্ডগুলির তালিকা পুনরুদ্ধার করুন । (কোনও রেকর্ড স্মৃতিতে নেই))

(খ) কারের IQueryableমডেল তা দেখার জন্য পাস করুন IEnumerable। (বৈধ। IQueryableপ্রসারিত IEnumerable।)

(গ) উপাত্ত থেকে ডেটা সেট এর রেকর্ডস, শিশু সত্তা এবং বৈশিষ্ট্যগুলি পরীক্ষা করে দেখুন এবং অ্যাক্সেস করুন। (ব্যতিক্রম হতে পারে!)

সম্ভাব্য সমস্যা

(1) IEnumerableঅলস লোডিংয়ের প্রচেষ্টা এবং আপনার ডেটা প্রসঙ্গের মেয়াদ শেষ হয়ে গেছে। ব্যতিক্রম ছুঁড়ে দেওয়া হয়েছে কারণ সরবরাহকারী আর উপলব্ধ নেই।

(২) সত্তা ফ্রেমওয়ার্ক সত্তা প্রক্সিগুলি সক্ষম (ডিফল্ট), এবং আপনি কোনও মেয়াদোত্তীর্ণ ডেটা প্রসঙ্গে একটি সম্পর্কিত (ভার্চুয়াল) অবজেক্টে অ্যাক্সেস করার চেষ্টা করছেন। (1) হিসাবে একই।

(3) একাধিক সক্রিয় ফলাফল সেট (MARS)। যদি আপনি IEnumerableকোনও foreach( var record in resultSet )ব্লকের মধ্যে পুনরাবৃত্তি করছেন এবং একযোগে অ্যাক্সেসের চেষ্টা করছেন record.childEntity.childPropertyতবে ডেটা সেট এবং আপেক্ষিক সত্তা উভয়ের অলস লোডিংয়ের কারণে আপনি মার্সের সাথে শেষ করতে পারেন। এটি আপনার সংযোগ স্ট্রিংয়ে সক্ষম না করা থাকলে এটি একটি ব্যতিক্রম ঘটায়।

সমাধান

  • আমি খুঁজে পেয়েছি যে সংযোগ স্ট্রিংয়ে মার্স সক্ষম করা অবিশ্বাস্যভাবে কাজ করে। আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি মার্স এড়িয়ে চলুন যদি না এটি ভালভাবে বোঝে এবং স্পষ্টভাবে পছন্দসই হয়।

অনুরোধ করে ক্যোয়ারী এবং স্টোর ফলাফলগুলি সম্পাদন করুন এটি resultList = resultSet.ToList() আপনার সত্তাগুলি স্মরণে থাকা নিশ্চিত করার সর্বাধিক সোজা উপায় বলে মনে হচ্ছে।

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


9

"আইইনিউমারেবল" এবং "আইকিউয়েরেবল" এর মধ্যে প্রধান পার্থক্যটি যেখানে ফিল্টার যুক্তি কার্যকর করা হয় about একটি ক্লায়েন্ট পক্ষের (মেমরি) এবং অন্যটি ডাটাবেসে মৃত্যুদন্ড কার্যকর করে।

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

অন্যদিকে একই ক্ষেত্রে আমরা যদি "আইকিউয়েরেবল" ব্যবহার করি তবে এটি সরাসরি ডাটাবেসে আইস্যাকটিভ ফিল্টার প্রয়োগ করবে যা সেখান থেকে সরাসরি 900 টি সক্রিয় ব্যবহারকারীকে ফিরিয়ে দেবে।

রেফারেন্স লিংক


পারফরম্যান্সের দিক থেকে কোনটি অনুকূলিত এবং হালকা ওজনের?
সিটিকোর স্যাম

অপ্টিমাইজড এবং হালকা ওজনের ক্ষেত্রে @ সাম "আইকুয়্যারেবল" বেশি পছন্দ করা হয়।
তাবিশ উসমান

6

আমরা উভয়কে একইভাবে ব্যবহার করতে পারি এবং তারা পারফরম্যান্সে কেবল আলাদা are

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

উদাহরণস্বরূপ, আমরা শীর্ষ 10 গ্রাহককে নিতে চাই যাদের নাম 'নিমাল' দিয়ে শুরু হয়। এই ক্ষেত্রে নির্বাচিত ক্যোয়ারী হিসাবে উত্পন্ন হবে select top 10 * from Customer where name like ‘Nimal%’

তবে আমরা যদি আইনিউমেন্টেবল ব্যবহার করি তবে ক্যোয়ারীটি পছন্দ হবে select * from Customer where name like ‘Nimal%’এবং সেরা দশটি সি # কোডিং স্তরে ফিল্টার হবে (এটি ডাটাবেস থেকে সমস্ত গ্রাহকের রেকর্ড পেয়েছে এবং সেগুলিকে সি # তে পাস করবে)।


5

প্রথম 2 টি ছাড়াও সত্যিই ভাল উত্তর (ড্রাই এবং জ্যাকব দ্বারা):

সংখ্যাযুক্ত ইন্টারফেসটি সিস্টেম.কলেকশন নেমস্পেসে রয়েছে।

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

যখন কোয়েরিটি কার্যকর করা হয়, তখন অগণিত সমস্ত ডেটা লোড করে এবং যদি আমাদের এটি ফিল্টার করতে হয় তবে ফিল্টারিং নিজেই ক্লায়েন্টের পক্ষেই করা হয়।

আইকিউয়েরেবল ইন্টারফেসটি সিস্টেম.লিংক নেমস্পেসে অবস্থিত।

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

কী বেছে নেবে?

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

যদি আপনার ফিরে আসা ডেটার পুরো সেটটি না প্রয়োজন তবে কেবলমাত্র কিছু ফিল্টারযুক্ত ডেটা প্রয়োজন হয় তবে আইকিউচারেবল ব্যবহার করা ভাল।


0

উপরের পাশাপাশি, এটি আকর্ষণীয় যে আপনি যদি এর IQueryableপরিবর্তে ব্যবহার করেন তবে আপনি ব্যতিক্রম পেতে পারেন IEnumerable:

নিম্নলিখিতটি যদি কাজ করে তবে productsতা ঠিক কাজ করে IEnumerable:

products.Skip(-4);

তবে যদি productsএটি হয় IQueryableএবং এটি কোনও ডিবি টেবিল থেকে রেকর্ডগুলি অ্যাক্সেস করার চেষ্টা করছে, তবে আপনি এই ত্রুটিটি পাবেন:

অফসেটের ধারাটিতে নির্দিষ্ট করা অফসেটটি নেতিবাচক নাও হতে পারে।

নিম্নলিখিত ক্যোয়ারী নির্মিত হয়েছিল কারণ এটি:

SELECT [p].[ProductId]
FROM [Products] AS [p]
ORDER BY (SELECT 1)
OFFSET @__p_0 ROWS

এবং অফসেটের নেতিবাচক মান থাকতে পারে না।

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