PDA

View Full Version : تفاوت IQueryable و IEnumerable



Mostafa_Dindar
دوشنبه 30 فروردین 1389, 00:14 صبح
سلام ،


يك پروژه رو دارم برسي ميكنم ، نوع خروجي متدها گاهي IQueryable ، گاهي IEnumerable و گاهي IList هست .

از كدومشون بهتره استفاده كنم ؟ تفاوتهاشون در چيه ؟

مرسي

--------------------------------------
پاورقي :

با طرز كار Lambada Expression و Extension Method ها آشنايي دارم ولي چيزي از Lambada Expression Tree متوجه نشدم :عصبانی++:

اَرژنگ
دوشنبه 30 فروردین 1389, 03:05 صبح
سلام ،


يك پروژه رو دارم برسي ميكنم ، نوع خروجي متدها گاهي IQueryable ، گاهي IEnumerable و گاهي IList هست .

از كدومشون بهتره استفاده كنم ؟ تفاوتهاشون در چيه ؟

مرسي

--------------------------------------
پاورقي :

با طرز كار Lambada Expression و Extension Method ها آشنايي دارم ولي چيزي از Lambada Expression Tree متوجه نشدم :عصبانی++:

بستگی دارد، بنابر اینکه خروجی متد چی باید باشد که نشد طراحی! هر کدامشان خصوصیاتی دارند که در جایه خودشان بکار میاند. در ضمن ما با متدها طراحی نمیکنیم، کلاسهایه پروژه و اینکه چه خصوصیاتی را باید ارضا کنیم هم ابستگی دارد

Mostafa_Dindar
دوشنبه 30 فروردین 1389, 07:59 صبح
بستگی دارد، بنابر اینکه خروجی متد چی باید باشد که نشد طراحی! هر کدامشان خصوصیاتی دارند که در جایه خودشان بکار میاند. در ضمن ما با متدها طراحی نمیکنیم، کلاسهایه پروژه و اینکه چه خصوصیاتی را باید ارضا کنیم هم ابستگی دارد

سلام،

دوست من ، من منظور شما رو متوجه نشدم . من تفاوت نوع برگشتي IQueryable و IEnumerable رو پرسيدم ،در اينجا كاري به نحوع طراحي يا معماري ندارم ، سوال من در واقع اين هست كه IQueryable چه مزايا با معايبي نسبت به IEnumerable دارد .

در مقالات كه جستجو كردم ، متوجه شدم مربوط به Lambada Expression Tree و .. هست كه براي من مفهموم نيست .

الان كه Definition هاي اين دو Interface رو برسي ميكنم متوجه شدم كه IQueryable از IEnumerable ارث بري ميكند و ...

using System.Collections;
using System.Collections.Generic;

namespace System.Linq
{
// Summary:
// Provides functionality to evaluate queries against a specific data source
// wherein the type of the data is known.
//
// Type parameters:
// T:
// The type of the data in the data source.
public interface IQueryable<T> : IEnumerable<T>, IQueryable, IEnumerable
{
}
}

using System.Collections;
using System.Runtime.CompilerServices;

namespace System.Collections.Generic
{
// Summary:
// Exposes the enumerator, which supports a simple iteration over a collection
// of a specified type.
//
// Type parameters:
// T:
// The type of objects to enumerate.
public interface IEnumerable<T> : IEnumerable
{
// Summary:
// Returns an enumerator that iterates through the collection.
//
// Returns:
// A System.Collections.Generic.IEnumerator<T> that can be used to iterate through
// the collection.
IEnumerator<T> GetEnumerator();
}
}

adinochestva
دوشنبه 30 فروردین 1389, 08:26 صبح
IQueryable معمولا استفاده از بانک های اطلاعاتی هست و IEnumerable برای دسترسی به داده در حافظه.
وقتی شما حلقه ای را استفاده می کنید با IEnumerable<T> در هر چرخش فقط یک ردیف بازگردانده می شه و به قولی پلیه ای عمل می کند ولی دستوری که IQueryable<T> بر می گردونه Late binding هست به این معنا که در اولین مورد استفاده تمام ردیف ها از مبدا گرفته شده و اولین ردیف به شما تحویل می شود
در کل مبدا اطلاعات هست که این دو را جدا می کند.

اَرژنگ
دوشنبه 30 فروردین 1389, 09:01 صبح
سلام،

دوست من ، من منظور شما رو متوجه نشدم . من تفاوت نوع برگشتي IQueryable و IEnumerable رو پرسيدم ،در اينجا كاري به نحوع طراحي يا معماري ندارم ، سوال من در واقع اين هست كه IQueryable چه مزايا با معايبي نسبت به IEnumerable دارد .


اینترفیسها مزایا و یا معایب ندارند، اینترفیس از تعریف قابلیت‌هایی که باید پیاده بشه و یا اینکه یک ابجکت حمایت میکند بیشتر چیزی نیستند.

ممکنه که شما کاری به طراحی و یا معماری نداشته باشید ولی اینترفیسها دقیقاً برایه همین کارند، کدی در خودشان پیاده نمیکنند ولی اینکه از چه قابلیتهایی پشتیبانی شده را صریحاً اعلام میکنند.

وقتی که با اینترفیس کار میکنید بررسی کردن مزایا و یا معایب بیمعنیه، چونکه اینترفیسها فقط کاربرد را تعریف میکنند نه نحوه کار را.

Mostafa_Dindar
دوشنبه 30 فروردین 1389, 09:40 صبح
IQueryable معمولا استفاده از بانک های اطلاعاتی هست و IEnumerable برای دسترسی به داده در حافظه.
وقتی شما حلقه ای را استفاده می کنید با IEnumerable<T> در هر چرخش فقط یک ردیف بازگردانده می شه و به قولی پلیه ای عمل می کند ولی دستوری که IQueryable<T> بر می گردونه Late binding هست به این معنا که در اولین مورد استفاده تمام ردیف ها از مبدا گرفته شده و اولین ردیف به شما تحویل می شود
در کل مبدا اطلاعات هست که این دو را جدا می کند.

سلام ،

ممنون دوست عزيز ، و لي اگر من منظور شما رو درست متوجه شده باشم ، حرف شما با گفته Scott Guttrie (http://weblogs.asp.net/scottgu/archive/2007/04/21/new-orcas-language-feature-query-syntax.aspx) در منافات است :


One of the nice characteristics of IEnumerable<T> interfaces is that objects that implement them can defer the actual execution of the queries until a developer first attempts to iterate over the values (this is accomplished using the "yield" construct that was first introduced with C# 2.0 in VS 2005). LINQ and query syntax expressions take advantage of this feature, and defer the actual execution of queries until the first time you loop over the results. If you never iterate over the IEnumerable<T> result, then the query is never executed.

For example, consider the below LINQ to SQL example:

http://www.scottgu.com/blogposts/querysyntax/step15.jpg

The database will be hit and the values to populate our Category objects will be retrieved not when the query syntax expression is declared - but rather when we first try and loop over the results (indicated above with the red arrow).

همانطور كه ملاحظه ميكنيد حتي هنگام استفاده از IEnumerable<t> نيز تا هنگامي كه برنامه نويس داخل IEnumerable پيمايش نكند كوئري انجام نميشود .

( البته اگر منظور شما از LateBinding تاخير در اجراي كوئري باشد ، در غير اينصورت لطف كنيد و در اين مورد بيشتر توضيح دهيد )

Mostafa_Dindar
دوشنبه 30 فروردین 1389, 09:50 صبح
اینترفیسها مزایا و یا معایب ندارند، اینترفیس از تعریف قابلیت‌هایی که باید پیاده بشه و یا اینکه یک ابجکت حمایت میکند بیشتر چیزی نیستند.

ممکنه که شما کاری به طراحی و یا معماری نداشته باشید ولی اینترفیسها دقیقاً برایه همین کارند، کدی در خودشان پیاده نمیکنند ولی اینکه از چه قابلیتهایی پشتیبانی شده را صریحاً اعلام میکنند.



حرف شما در مورد اينترفيس ها كاملا صحيح هست ، اينترفيس ها يك سري قابليت ها ( سرويسها ) داردند كه در صوتي كه از اون اينترفيس ارث بري كنيم و اون سرويس رو در اون كلاس پياده سازي كنيم ، ميتونيم از اون سرويس استفاده كنيم .


وقتی که با اینترفیس کار میکنید بررسی کردن مزایا و یا معایب بیمعنیه، چونکه اینترفیسها فقط کاربرد را تعریف میکنند نه نحوه کار را.
اجازه بديد به صورت ديگري سوالم رو مطرح كنم ، شايد نتونستم منظورم رو برسونم .
همانطور كه شما فرموديد اينترفيس ها كاربردهاي متفاوتي رو تعريف ميكنند كه IQueryable و IEnumerable نيز كاربردهاي متفاوتي رو تعريف ميكنند در غير اينصورت بي معني خواهد بود كه 2 اينترفيس يكسان داشته باشيم .

چه موقع بهتر( يا ضرورت) است نوع برگشتي از نوع اينترفيس IQueryable باشد يا اينترفيس IEnumerable ؟

پاورقي :

در اين پست (http://stackoverflow.com/questions/2433306/whats-the-difference-between-iqueryable-and-ienumerable) يكي به اين سوال پاسخ داده كه باز هم من متوجه نميشم . اگر شما متوجه شديد ، لطف كنيد و براي ما هم توضيح دهيد

adinochestva
دوشنبه 30 فروردین 1389, 10:59 صبح
حرف شما صحیح . منظور بنده اینه که در IEnumerable وقتی پیمایش شروع میشه تک - تک ردیف ها از منبع پرفته می شود ولی در IQueryable در ابتدای پیمایش کل سطرهایی که با دستور شما در منبع وجود دارد از منبع گرفته شده و در حافظه قرار می گیرد.
در مورد Expression Tree همانطور که تو لینکی هم که خودتون قرار داید در کد زیر :


IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

شرط x.Age > 18 در هر پیمایش بر روی تک تک سطرها یک بار تست می شود
ولی در


IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

شرط x.Age > 18 به کدی در پشت صحنه ( SQL ( تبدیل می شود که فقط سطوری که فیلد Age آنها از 18 بزگتر می باشند رو برگردونه

اَرژنگ
دوشنبه 30 فروردین 1389, 11:30 صبح
چه موقع بهتر( يا ضرورت) است نوع برگشتي از نوع اينترفيس IQueryable باشد يا اينترفيس IEnumerable ؟


طبقه لینکی که شما فرستادید و جواب adinochestva فرستادند ۲ حالت میشه مثال زد:

مثال اول: فرض کنیم ۱میلیون رکورد در داتابیس داریم و فقط به یکمقدار کمی از این رکوردها احتیاج داریم، به این شکل بهتر این است که فقط رکوردهایه که لازم هستند برگردانده بشند، به این شکل شرط فیلتر در طرف داتابیس کمپایل و عمل میشه، ممکن است که در نتیجه شما فقط ۱۰ تا رکورد بدست بیارید، IQueryable را باید ترجیح بدیم ، چونکه IEnumerable تمام ۱ میلیون رکورد را برمیگردانه و شرط را یکی یکی بر تمامش اعمال میکنه و به شما همان ۱۰ رکورد را برمیگردانه (بدانه اینکه در تاخیری که حاصل شده ممکن است هم اکنون ۱۱ و یا ۹ تا رکورد در داتابیس با شرطمان بخونه).

مثال ۲: فرض کنیم تمام اشیا در حافظه هستند، مانند تمام کنترلهایه یک فرم، و ما فقط احتیاج به لیست تکست باکسها داریم، در این حالت (من) فرقی بین استفاده از IEnumerable و یا IQueryable نمیبینم ، به شرط اینکه هر دو حمایت شده باشند.

۲ نقطه :
۱.زمانی که در مورد اینترفیسها صحبت میکنیم نوع برگشتي مهم نیست ، چونکه هر کلاسی ممکن است که برگشت داده شده باشد بلک قابلیت اینترفیسی که مورد نظر است مهمه.
به این شکل یک کلاس میتواند از هر دو اینترفیس پشتیبانی کند، ولی اگر شما به طریق اینترفیس IQueryable با ابجکت برخورد کنید ممکن است که رفتار مختلفی را ببینید تا اینکه با ابجکت از طریق IEnumerable برخورد کنید.

۲. شما میتوانید IEnumerable را فقط پیاده کنید ولی IQueryable باید IEnumerable را هم پیاده کند، اگر به شکل Explicit صریحتاً پیاده‌اشان کنید میتواناید رفتارهایه مختلف را با هر کدام نمایش بدید.