IEnumerable <T> එදිරිව IQueryable <T> වෙත ආපසු යාම


1096

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;

Answers:


1793

ඔව්, දෙකම ඔබට කල් දැමූ ක්‍රියාත්මක කිරීමක් ලබා දෙනු ඇත .

වෙනස වන්නේ IQueryable<T>LINQ-to-SQL (LINQ.-to-anything really) වැඩ කිරීමට ඉඩ දෙන අතුරු මුහුණතයි. එබැවින් ඔබ ඔබේ විමසුම තව දුරටත් පිරිපහදු කරන්නේ නම් IQueryable<T>, එම විමසුම හැකි නම් දත්ත ගබඩාවේ ක්‍රියාත්මක වේ.

සඳහා IEnumerable<T>, ඔහු ඒ මුල් විමසුම හා ගැලපෙන සියලු වස්තු දත්ත සමුදායෙන් මතකය වෙත පටවනු සිදු ඇති බව තේරුම, LINQ-කිරීමට වස්තුව වනු ඇත.

කේතයෙන්:

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

එම කේතය SQL ක්‍රියාත්මක කරන්නේ රන් පාරිභෝගිකයින් පමණක් තෝරා ගැනීම සඳහා ය. පහත කේතය, අනෙක් අතට, දත්ත සමුදායේ මුල් විමසුම ක්‍රියාත්මක කර, පසුව රන් නොවන ගනුදෙනුකරුවන් මතකයේ පෙරහන් කරයි:

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

මෙය බෙහෙවින් වැදගත් වෙනසක් වන අතර, වැඩ කිරීමෙන් IQueryable<T>බොහෝ විට දත්ත සමුදායෙන් පේළි විශාල ප්‍රමාණයක් ආපසු ලබා දීමෙන් ඔබව ගලවා ගත හැකිය. තවත් ප්‍රධාන උදාහරණයක් වන්නේ පේජිං කිරීමයි: ඔබ භාවිතා කරන්නේ නම් Takeසහ ක්‍රියාත්මක Skipවන්නේ නම් IQueryable, ඔබට ලැබෙන්නේ ඉල්ලූ පේළි ගණන පමණි; එසේ කිරීමෙන් IEnumerable<T>ඔබගේ සියලු පේළි මතකයේ පැටවෙනු ඇත.


33
විශිෂ්ට පැහැදිලි කිරීමක්. IQueryable ට වඩා IEnumerable වඩා සුදුසු අවස්ථා තිබේද?
fjxx

8
එබැවින් අපට මතක වස්තුව විමසීමට IQueryable භාවිතා කරන්නේ නම්, ඒවා IEnumerable සහ IQueryable අතර වෙනසක් නොවනු ඇතැයි අපට පැවසිය හැකිද?
තාරික්

11
අවවාදයයි: ප්‍රකාශ කර ඇති ප්‍රශස්තිකරණය නිසා IQueryable යනු පෙළඹවීමේ විසඳුමක් විය හැකි නමුත්, එය නිධිය හෝ සේවා ස්ථරය පසුකර යාමට ඉඩ නොදිය යුතුය. මෙය "LINQ ප්‍රකාශන ගොඩගැසීම" නිසා ඇති වන පොදු කාර්ය වලින් ඔබේ දත්ත සමුදාය ආරක්ෂා කිරීමයි.
යෝරෝ

50
@fjxx ඔව්. ඔබේ මුල් ප්‍රති result ලය මත නැවත නැවත පෙරීම අවශ්‍ය නම් (අවසාන ප්‍රති .ල කිහිපයක්). IQueryable අතුරුමුහුණතෙහි එය සිදු කිරීමෙන් දත්ත සමුදායට රවුම් තීරු කිහිපයක් ලැබෙනු ඇත, එහිදී IEnumerable මත සිදු කිරීම මතකයේ පෙරීම සිදු කරයි, එය වේගවත් කරයි (දත්ත ප්‍රමාණය විශාල නොවේ නම්)
Per Hornshøj-Schierbeck

34
කැමති IEnumerableවීමට තවත් හේතුවක් IQueryableනම්, සියලු ලින්ක් මෙහෙයුම් සඳහා සියලුම ලින්ක් සපයන්නන් සහාය නොදක්වයි. එබැවින් ඔබ කරන්නේ කුමක්දැයි ඔබ දන්නා තාක් කල්, ඔබට IQueryableවිමසුම LINQ සැපයුම්කරු වෙත (LINQ2SQL, EF, NHibernate, MongoDB ආදිය) තල්ලු කිරීමට භාවිතා කළ හැකිය . නමුත් ඔබ වෙනත් කේතයකට අවශ්‍ය ඕනෑම දෙයක් කිරීමට ඉඩ දුන්නොත් IQueryableඅවසානයේදී ඔබ කරදරයට පත්වනු ඇත, මන්ද සමහර සේවාදායක කේත කොතැනක හෝ සහාය නොදක්වන ක්‍රියාවක් භාවිතා කළ බැවිනි. IQueryableනිධිය හෝ ඊට සමාන ස්ථරයක් පසුකර “වනයට” මුදා නොහරින ලෙස මම නිර්දේශ කරමි .
අවිෂ්

311

ඉහළම පිළිතුර හොඳයි, නමුත් එහි අතුරු මුහුණත් දෙක එකිනෙකට වෙනස් වන්නේ කෙසේද යන්න පැහැදිලි කරන ප්‍රකාශන ගස් ගැන සඳහන් නොවේ. මූලික වශයෙන්, LINQ දිගු වල සමාන කට්ටල දෙකක් තිබේ. Where(), Sum(), Count(), FirstOrDefault()කාර්යයන් පිළිගන්නා හා එක් ප්රකාශන පිළිගන්නා බව එක්: ආදිය සියලු ආකාර දෙකකින් ඇත.

  • මෙම IEnumerableඅනුවාදය අත්සන:Where(Func<Customer, bool> predicate)

  • මෙම IQueryableඅනුවාදය අත්සන:Where(Expression<Func<Customer, bool>> predicate)

ඔබ බොහෝ විට ඒ දෙකම නොදැනුවත්වම භාවිතා කර ඇත්තේ දෙකම සමාන වාක්‍ය ඛණ්ඩයක් ලෙස හැඳින්වෙන බැවිනි:

උදා: සහ Where(x => x.City == "<City>")දෙකෙහිම ක්‍රියා කරයිIEnumerableIQueryable

  • එකතුවක් භාවිතා Where()කරන විට IEnumerable, සම්පාදකයා විසින් සම්පාදනය කරන ලද ශ්‍රිතයක් වෙත යොමු කරයිWhere()

  • එකතුවක් භාවිතා Where()කරන විට IQueryable, සම්පාදකයා ප්‍රකාශන ගසක් වෙත යොමු Where()කරයි. ප්‍රකාශන ගසක් පරාවර්තන පද්ධතියට සමාන නමුත් කේතය සඳහා ය. සම්පාදකයා ඔබේ කේතය දත්ත ව්‍යුහයක් බවට පරිවර්තනය කරයි, එය ඔබේ කේතය පහසුවෙන් ජීර්ණය කළ හැකි ආකෘතියකින් කරන දේ විස්තර කරයි.

මෙම ප්‍රකාශන ගස ගැන කරදර වන්නේ ඇයි? මට අවශ්‍ය Where()මගේ දත්ත පෙරීමටයි. ප්‍රධාන හේතුව වන්නේ EF සහ Linq2SQL ORM වලට ප්‍රකාශන ගස් සෘජුවම SQL බවට පරිවර්තනය කළ හැකි අතර එහිදී ඔබේ කේතය වඩා වේගයෙන් ක්‍රියාත්මක වේ.

ඔහ්, එය නිදහස් කාර්ය සාධනයක් ලෙස පෙනේ, මම AsQueryable()එම අවස්ථාවේ දී සෑම තැනකම භාවිතා කළ යුතුද ? නැත, IQueryableප්‍රයෝජනවත් වන්නේ යටින් පවතින දත්ත සැපයුම්කරුට එය සමඟ යමක් කළ හැකි නම් පමණි. සාමාන්ය වගේ දෙයක් බවට පත් Listකිරීමට IQueryableඔබ කිසිදු ප්රතිලාභයක් ලැබෙන්නේ නැත.


9
IMO එය පිළිගත් පිළිතුරට වඩා හොඳයි. කෙසේ වෙතත්, මට එක දෙයක් ලැබෙන්නේ නැත: නිත්‍ය වස්තූන් සඳහා IQueryable කිසිදු ප්‍රතිලාභයක් ලබා නොදේ, හරි, නමුත් එය කිසිම ආකාරයකින් නරකද? මක්නිසාද යත් එය කිසිදු ප්‍රතිලාභයක් ලබා නොදෙන්නේ නම්, IEnumerable වලට වැඩි කැමැත්තක් දැක්වීමට එය ප්‍රමාණවත් නොවන බැවින් එම ස්ථානය පුරාම IQueryable භාවිතා කිරීමේ අදහස වලංගු වේ.
සර්ජි ටචෙනොව්

1
සර්ජි, IQueryable IEnumerable දිගු කරයි, එබැවින් IQueryable භාවිතා කරන විට IEnumerable ක්ෂණිකකරණයකට වඩා මතකයට පටවනු ලැබේ! ඉතින් මෙන්න තර්කයක්. ( stackoverflow.com/questions/12064828/… c ++ මට මෙය උපුටා දැක්විය හැකි යැයි සිතුවද)
වයිකිං

මෙය හොඳම පිළිතුර වීම ගැන සර්ජි සමඟ එකඟ වීම (පිළිගත් පිළිතුර හොඳයි). මගේ අත්දැකීම් අනුව, IQueryableකාර්යයන් විග්‍රහ නොකරන ලෙසට මම එය එකතු කරමි IEnumerable: නිදසුනක් ලෙස, a හි 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.
ජීන්-ඩේවිඩ් ලාන්ස්

1
වෙනස අවබෝධ කර ගැනීම සඳහා මෙය ඉතා ප්‍රයෝජනවත් තොරතුරු වේ, නමුත් ඉහළම පිළිතුර වඩාත් නිවැරදියි යන ප්‍රශ්නය වූයේ “එකක් අනෙකට වඩා කැමති විය යුත්තේ කවදාද?” සහ “වෙනස කුමක්ද?” නොවේ.
ස්කොපර්ලොයිට්

ErSergeiTachenov IQueryableසෑම තැනකම භාවිතා කිරීම සීමාවක් ඇත: සම්පාදකයාට සෑම C # ප්‍රකාශනයක්ම ප්‍රකාශන ගසක් බවට පරිවර්තනය කළ නොහැක. නියෝජිත වර්ගයක් (උදා Func<T, bool>) අපේක්ෂා කරන සන්දර්භයක් තුළ ඔබ ලැම්බඩා සින්ටැක්ස් භාවිතා කරන විට , සම්පාදකයා නිත්‍ය C # ක්‍රමයක් නිර්මාණය කරයි, එබැවින් ඔබට ඕනෑම C # සින්ටැක්ස් භාවිතා කළ හැකිය.
සෙව් ස්පිට්ස්

85

ඔව්, දෙකම විලම්බිත ක්‍රියාත්මක කිරීම භාවිතා කරයි. SQL සේවාදායක පැතිකඩ භාවිතා කරමින් වෙනස පැහැදිලි කරමු ....

අපි පහත කේතය ක්‍රියාත්මක කරන විට:

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);

SQL සේවාදායක පැතිකඩ තුළ අපට සමාන විධානයක් හමු වේ:

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

වාර්තා මිලියනයක් ඇති වෙබ් ලොග් වගුවකට එරෙහිව එම කේත කොටස ක්‍රියාත්මක කිරීමට ආසන්න වශයෙන් තත්පර 90 ක් ගතවේ.

ඉතින්, සියළුම වගු වාර්තා වස්තුවක් ලෙස මතකයට පටවනු ලැබේ, පසුව එක් එක් සමඟ .එහි () එය මෙම වස්තූන්ට එරෙහිව මතකයේ තවත් පෙරණයක් වනු ඇත.

ඉහත උදාහරණය IQueryableවෙනුවට අපි භාවිතා කරන විට IEnumerable(දෙවන පේළිය):

SQL සේවාදායක පැතිකඩ තුළ අපට සමාන විධානයක් හමු වේ:

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

මෙම කේත කොටස භාවිතා කර ක්‍රියාත්මක කිරීමට ආසන්න වශයෙන් තත්පර හතරක් ගත වේ IQueryable.

IQueryable හි දේපලක් Expressionඇති අතර එය ගස් ප්‍රකාශනයක් ගබඩා කරන අතර resultඑය අපගේ උදාහරණයේ භාවිතා කරන විට නිර්මාණය කිරීම ආරම්භ කරයි (එය විලම්බිත ක්‍රියාත්මක කිරීම ලෙස හැඳින්වේ), අවසානයේදී මෙම ප්‍රකාශනය දත්ත සමුදා එන්ජිම මත ධාවනය කිරීම සඳහා SQL විමසුමකට පරිවර්තනය වේ.


5
IEnumerable වෙත වාත්තු කිරීමේදී මෙය මට උගන්වයි, යටින් පවතින IQueryable හි IQueryable දිගු කිරීමේ ක්‍රමය නැති වේ.
යිපින්

58

දෙකම ඔබට කල් දැමූ ක්‍රියාත්මක කිරීමක් ලබා දෙනු ඇත, ඔව්.

අනෙකට වඩා කැමති දේ සඳහා, එය ඔබගේ යටින් පවතින දත්ත ප්‍රභවය කුමක්ද යන්න මත රඳා පවතී.

නැවත ලබා දීමෙන් IEnumerableඔබගේ එකතුව විමසීමට ස්වයංක්‍රීයව ධාවන කාලයට LINQ to Objects භාවිතා කිරීමට බල කෙරෙනු ඇත.

නැවත ලබා දීමෙන් IQueryable(එය ක්‍රියාත්මක IEnumerableකරන), ඔබේ විමසුම යටින් පවතින ප්‍රභවයට වඩා හොඳින් ක්‍රියා කළ හැකි දෙයකට පරිවර්තනය කිරීමට අමතර ක්‍රියාකාරීත්වයක් සපයයි (LINQ to SQL, LINQ to XML, ආදිය).


31

පොදුවේ ගත් කල මම පහත සඳහන් දෑ නිර්දේශ කරමි:

  • IQueryable<T>ක්‍රියාත්මක කිරීමට පෙර ඔබ ආපසු එන විමසුම පිරිපහදු කිරීමට ඔබේ ක්‍රමය භාවිතා කරමින් සංවර්ධකයා සක්‍රීය කිරීමට අවශ්‍ය නම් ආපසු යන්න .

  • IEnumerableගණනය කිරීම සඳහා ඔබට වස්තු සමූහයක් ප්‍රවාහනය කිරීමට අවශ්‍ය නම් ආපසු යන්න .

ක සිතන්න IQueryableඅ (ඔබට අවශ්ය නම් ඔබට ශුද්ධ හැකි) දත්ත සඳහා "විමසුම" - ඒ මොකක්ද ඒ ලෙස. An IEnumerableයනු ඔබට ගණනය කළ හැකි වස්තු සමූහයකි (දැනටමත් ලැබී ඇති හෝ නිර්මාණය කර ඇති).


2
"ගණනය කළ හැකිය," නැත "ගණනය කළ නොහැක."
කේසි

30

මීට පෙර බොහෝ දේ පවසා ඇත, නමුත් මුල් වලට ආපසු, වඩාත් තාක්ෂණික ආකාරයකින්:

  1. IEnumerable ඔබට ගණනය කළ හැකි මතකයේ ඇති වස්තු එකතුවකි - මතකයේ ඇති අනුක්‍රමයක් මඟින් එය හරහා නැවත ගමන් කිරීමට ඉඩ සලසයි ( foreachලූපය තුළ එය පහසු කරවයි , නමුත් ඔබට IEnumeratorපමණක් යා හැකි වුවද ). ඒවා මතකයේ රැඳේ.
  2. IQueryable ප්‍රකාශන ගසක් වන අතර එය යම් අවස්ථාවක දී අවසාන ප්‍රති .ලය ගණනය කිරීමේ හැකියාව ඇති වෙනත් දෙයකට පරිවර්තනය කරනු ඇත . මම හිතන්නේ මෙය බොහෝ මිනිසුන් ව්‍යාකූල කරයි.

ඔවුන්ට පැහැදිලිවම විවිධ අර්ථයන් ඇත.

IQueryableLINQ සමස්ථ ශ්‍රිත (එකතුව, ගණන්, ආදිය) හෝ ටොලිස්ට් [අරාව, ශබ්ද කෝෂය, වැනි නිකුතු API කැඳවූ විගසම යටින් පවතින විමසුම් සැපයුම්කරු විසින් ප්‍රකාශන ගසක් (විමසුමක්, සරලව) පරිවර්තනය කරනු ලැබේ. ..]. හා IQueryableක්රියාත්මක ද විරුද්ධ IEnumerable, IEnumerable<T>එසේ බව ඔවුන් විමසුම නියෝජනය නම් ඒ විමසුම ප්රතිඵලයක් ශාඛාවයි ගත හැක. එයින් අදහස් වන්නේ IQueryable යනු විමසුම් පමණක් විය යුතු නැති බවයි. නිවැරදි පදය නම් ඒවා ප්‍රකාශන ගස් ය .

දැන් එම ප්‍රකාශන ක්‍රියාත්මක කරන්නේ කෙසේද සහ ඒවා දෙසට හැරෙන්නේ ඊනියා විමසුම් සපයන්නන් (ප්‍රකාශන ක්‍රියාකරුවන් අපට ඒවා ගැන සිතිය හැකිය).

ආයතන රාමු ලෝකයේ (අද්භූත යටින් පවතින දත්ත ප්‍රභව සැපයුම්කරු හෝ විමසුම් සැපයුම්කරු) IQueryableප්‍රකාශන දේශීය T-SQL විමසුම් වලට පරිවර්තනය කරනු ලැබේ . Nhibernateඔවුන් හා සමාන දේවල් කරයි. LINQ හි ඉතා හොඳින් විස්තර කර ඇති සංකල්ප අනුගමනය කරමින් ඔබට ඔබේම එකක් ලිවිය හැකිය : නිදසුනක් ලෙස, IQueryable සැපයුම්කරුගේ සම්බන්ධතාවයක් ගොඩ නැගීම , ඔබේ නිෂ්පාදන ගබඩා සැපයුම්කරුගේ සේවාව සඳහා අභිරුචි විමසුම් API ලබා ගැනීමට ඔබට අවශ්‍ය විය හැකිය.

එබැවින් මූලික වශයෙන්, IQueryableවස්තූන් අප විසින් පැහැදිලිව මුදා හරින තෙක් ඒවා SQL හෝ වෙනත් ඕනෑම දෙයකට නැවත ලිවීමට හා ඉදිරියට සැකසීම සඳහා ක්‍රියාත්මක කිරීමේ දාමය යවන තෙක් පද්ධතියට කියනු ලැබේ.

කිරීමට මෙන් ටිකක් ප්රමාද ක්රියාත්මක එය තියෙන්නේ LINQමතකයේ ප්රකාශනය ගසක් යෝජනා ක්රමය දක්වා පැවැත්වීමට හා සමහර ඒපීඅයි වූ අනුපිළිවෙල (එම සංඛ්යාව, ToList, ආදිය) එරෙහිව කැඳවා ඇත සෑම අවස්ථාවකදීම, එකම ඉල්ලීම මත ක්රියාත්මක බවට එය යැවීමට ලක්ෂණය.

දෙකෙහිම නිසි භාවිතය දැඩි ලෙස රඳා පවතින්නේ ඔබ විශේෂිත අවස්ථාව සඳහා මුහුණ දෙන කාර්යයන් මත ය. සුප්‍රසිද්ධ නිධිය රටාව සඳහා මම පෞද්ගලිකව නැවත පැමිණීම තෝරා ගනිමි IList, එය IEnumerableලැයිස්තු ඉක්මවා ඇත (දර්ශක සහ ඒ හා සමාන). එබැවින් IQueryableකේතයේ වෙනත් ඕනෑම තැනක සහ IEnumerable තුළ පමණක් භාවිතා කිරීම මගේ අවවාදයයි. බව testability පිලිබඳව උත්සුකතාවන් කියන්නේ නැහැ IQueryableවිරාම පහළ සහ නටඹුන් අවධානය වෙන් මූලධර්මය. ඔබ ගබඩාවලින් ප්‍රකාශනයක් ආපසු ලබා දෙන්නේ නම් පාරිභෝගිකයින්ට ඔවුන් කැමති පරිදි ස්ථර ස්ථරය සමඟ සෙල්ලම් කළ හැකිය.

අවුලට ටිකක් එකතු කිරීම :) (අදහස් දැක්වීමේ සාකච්ඡාවකින්)) ඒවා කිසිවක් මතකයේ ඇති වස්තූන් නොවේ, මන්ද ඒවා සැබෑ වර්ග නොවන බැවින් ඒවා වර්ගයක සලකුණු වේ - ඔබට ගැඹුරට යාමට අවශ්‍ය නම්. නමුත් එය හැඟීමක් (සහ පවා ඒකයි කරයි MSDN හි එය මේ ආකාරයෙන් තබා) ප්රකාශනය ගස් IQueryables බැවින්ද දී මතක ලෙස ගෙවී IEnumerables ගැන හිතන්න. කාරණය වන්නේ IQueryable අතුරුමුහුණත IEnumerable අතුරුමුහුණත උරුම කර ගැනීමයි, එවිට එය විමසුමක් නියෝජනය කරන්නේ නම්, එම විමසුමේ ප්‍රති results ල ගණනය කළ හැකිය. ගණනය කිරීම මඟින් IQueryable වස්තුවක් හා සම්බන්ධ ප්‍රකාශන ගස ක්‍රියාත්මක කිරීමට හේතු වේ. එබැවින්, ඇත්ත වශයෙන්ම, මතකයේ ඇති වස්තුවක් නොමැතිව ඔබට සැබවින්ම IEnumerable සාමාජිකයෙකු ඇමතිය නොහැක. ඔබ එසේ කළහොත් එය හිස් නොවේ නම් එය කෙසේ හෝ එහි ඇතුල් වනු ඇත. IQueryables යනු විමසීම් මිස දත්ත නොවේ.


3
IEnumerables සැමවිටම මතකයේ පවතින බවට කරන ප්‍රකාශය සත්‍ය වශයෙන්ම සත්‍ය නොවේ. IQueryable අතුරුමුහුණත IEnumerable අතුරුමුහුණත ක්‍රියාත්මක කරයි. මේ නිසා, ඔබට LINQ-to-SQL විමසුමක් නිරූපණය කරන අමු IQueryable එකක් IEnumerable අපේක්ෂා කරන දර්ශනයකට යොමු කළ හැකිය! ඔබගේ දත්ත සන්දර්භය කල් ඉකුත්වී ඇති බව හෝ ඔබ MARS (බහු ක්‍රියාකාරී ප්‍රති result ල කට්ටල) සමඟ ගැටලු ඇති කර ගැනීම ගැන ඔබ පුදුමයට පත් විය හැකිය.

එබැවින්, ඇත්ත වශයෙන්ම, මතකයේ ඇති වස්තුවක් නොමැතිව ඔබට සැබවින්ම IEnumerable සාමාජිකයෙකු ඇමතිය නොහැක. ඔබ එසේ කළහොත් එය හිස් නොවේ නම් එය කෙසේ හෝ එහි ඇතුල් වනු ඇත. IQueryables යනු විමසීම් මිස දත්ත නොවේ. නමුත් මම ඇත්තටම ඔබේ අදහස දකිමි. මම මේ ගැන අදහසක් එක් කරන්නම්.
අර්මාන් මැක්හිතාරියන්

Lex ඇලෙක්සැන්ඩර් ප්‍රිචාර්ඩ් ඒවා කිසිවක් මතකයේ ඇති වස්තූන් නොවන බැවින් ඒවා සැබෑ වර්ග නොවන බැවින් ඒවා වර්ගයක සලකුණු වේ - ඔබට ගැඹුරට යාමට අවශ්‍ය නම්. නමුත් IEnumerables මතකයේ එකතුවක් ලෙස සිතීම අර්ථවත් කරයි (සහ එම්එස්ඩීඑන් පවා මේ ආකාරයට එය තබයි) IQueryables ප්‍රකාශන ගස් ලෙස. කාරණය වන්නේ IQueryable අතුරුමුහුණත IEnumerable අතුරුමුහුණත උරුම කර ගැනීමයි, එවිට එය විමසුමක් නියෝජනය කරන්නේ නම්, එම විමසුමේ ප්‍රති results ල ගණනය කළ හැකිය. ගණනය කිරීම මඟින් IQueryable වස්තුවක් හා සම්බන්ධ ප්‍රකාශන ගස ක්‍රියාත්මක කිරීමට හේතු වේ.
අර්මාන් මැක්හිතාරියන්

25

පොදුවේ ඔබට අවශ්‍ය වන්නේ විමසුමේ මුල් ස්ථිතික වර්ගය වැදගත් වන තුරු සංරක්ෂණය කිරීමයි.

මේ හේතුව නිසා, ඔබට ඔබේ විචල්‍යය 'var' ලෙස අර්ථ දැක්විය හැකිය, IQueryable<>නැතහොත් IEnumerable<>ඔබ වර්ගය වෙනස් නොකරන බව ඔබ දැන ගනු ඇත.

ඔබ ආරම්භ කරන්නේ නම් IQueryable<>, ඔබට එය සාමාන්‍යයෙන් IQueryable<>වෙනස් කිරීමට යම් ප්‍රබල හේතුවක් ඇති වන තෙක් එය තබා ගැනීමට අවශ්‍ය වේ . එයට හේතුව ඔබට විමසුම් සකසනය හැකිතාක් තොරතුරු ලබා දීමට අවශ්‍ය වීමයි. උදාහරණයක් ලෙස, ඔබ භාවිතා කිරීමට යන්නේ ප්‍රති results ල 10 ක් පමණි (ඔබ කැඳවා ඇත Take(10)) එවිට ඔබට SQL සේවාදායකය ඒ ගැන දැන ගැනීමට අවශ්‍ය වන අතර එමඟින් එහි විමසුම් සැලසුම් ප්‍රශස්ත කර ඔබට භාවිතා කරන දත්ත පමණක් එවනු ඇත.

සිට වර්ගය වෙනස් කිරීමට හේතුවක් IQueryable<>කිරීමට IEnumerable<>ඔබ ක්රියාත්මක කිරීම බව සමහර දීර්ඝ කාර්යය ඉල්ලා සිටිනවා විය හැකියි IQueryable<>, ඔබේ විශේෂ වස්තුව දී අකාර්යක්ෂම හැසිරවිය හැකි හෝ එසේත් නැත්නම් හැන්ඩ්ල්. එවැනි අවස්ථාවකදී, ඔබට වර්ගය IEnumerable<>(විචල්‍ය වර්ගයකට පැවරීමෙන් IEnumerable<>හෝ AsEnumerableදීර් extension කිරීමේ ක්‍රමය භාවිතා කිරීමෙන් ) බවට පරිවර්තනය කිරීමට අවශ්‍ය විය හැකිය, එවිට ඔබ අමතනු ලබන ව්‍යාප්ති කාර්යයන් අවසන් වන්නේ Enumerableපන්තිය වෙනුවට Queryableපන්තියේ ඒවා ලෙස ය.


19

IEnumerable<T>LINQ විමසුම් ක්‍රියාකාරිත්වයට අනිසි ලෙස බලපාන්නේ කෙසේද යන්න පිළිබඳ කෙටි මූලාශ්‍ර කේත නියැදියක් සහිත බ්ලොග් සටහනක් ඇත : ආයතන රාමුව: IQueryable vs. IEnumerable .

අපි ගැඹුරට හාරා ප්‍රභවයන් දෙස බැලුවහොත්, පැහැදිලිවම වෙනස් විස්තාරණ ක්‍රම මේ සඳහා සුවඳ විලවුන් කර ඇති බව අපට පෙනේ 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.


12

මම මෑතකදී IEnumerablev IQueryable. භාවිතා කරන ඇල්ගොරිතම පළමුව ප්‍රති IQueryable.ල ලබා ගැනීම සඳහා විමසුමක් සිදු කළේය . මේවා පසුව ලූපයකට යවන ලද foreachඅතර, අයිතමයන් ආයතන රාමු (ඊඑෆ්) පන්තියක් ලෙස ක්ෂණිකව තහවුරු කරන ලදී. මෙම ඊඑෆ් පංතිය පසුව fromලින්ක් සිට එන්ටිටි විමසුමක වගන්තියේ භාවිතා කරන ලද අතර එහි ප්‍රති result ලය විය IEnumerable.

මම ආයතන සඳහා ඊඑෆ් සහ ලින්ක් වලට තරමක් අලුත් ය, එබැවින් බාධකය කුමක්දැයි සොයා ගැනීමට ටික කාලයක් ගත විය. මිනි ප්‍රොෆයිලිං භාවිතා කරමින්, මම විමසුම සොයාගත් අතර පසුව සියලු තනි මෙහෙයුම් IQueryableආයතන විමසුම සඳහා තනි ලින්ක් බවට පරිවර්තනය කළෙමි . මෙම IEnumerableතත්පර 15 ක් සහ IQueryableක්රියාත්මක කිරීමට තත්පර 0.5 ගියා. වගු තුනක් සම්බන්ධ වූ අතර, මෙය කියවීමෙන් පසු, IEnumerableවිමසුම ඇත්ත වශයෙන්ම මේස තුනක හරස් නිෂ්පාදනයක් සාදා ප්‍රති .ල පෙරීම බව මම විශ්වාස කරමි .

IQueryables නීතියක් ලෙස භාවිතා කිරීමට උත්සාහ කරන්න සහ ඔබේ වෙනස්කම් මැනිය හැකි වන පරිදි ඔබේ කාර්යය පැතිකඩ කරන්න.


හේතුව, IQueryable ප්‍රකාශන EF හි ස්වදේශීය SQL බවට පරිවර්තනය කර DB තුළම ක්‍රියාත්මක වන අතර IEnumerable ලැයිස්තු මතකයේ ඇති වස්තු වේ. ඔබ ගණන් කිරීම, එකතුව, හෝ ඕනෑම දෙයක් වැනි සමස්ත කාර්යයන් අමතා පසුව මතකයේ ක්‍රියාත්මක වන විට ඒවා ඩීබී වෙතින් ලබා ගනී. IQueryableඔබ එම API වලින් එකක් ඇමතූ පසු s ද මතකයේ සිරවී ඇති නමුත් එසේ නොවේ නම්, ඔබට ප්‍රකාශනය ස්ථරවල සිරස් අතට ගෙන API ඇමතුම ලැබෙන තෙක් පෙරහන් සමඟ සෙල්ලම් කළ හැකිය. නිර්මාණය ඉෙල ෙ ගැටලු මේ ආකාරයේ විසඳුමක් වනු ඇත හොඳ ලෙස හොඳින් සැලසුම් DAL;)
Arman McHitarian

11

පරස්පර විරෝධී ප්‍රතිචාර නිසා (බොහෝ දුරට IEnumerable අවට) කරුණු කිහිපයක් පැහැදිලි කිරීමට මම කැමතියි.

(1) අතුරු මුහුණත IQueryableදිගු කරයි IEnumerable. ( දෝෂයකින් තොරව IQueryableඅපේක්ෂා කරන දෙයකට ඔබට යැවිය හැකිය IEnumerable.)

(2) ප්‍රති IQueryableand IEnumerableල කට්ටලය හරහා නැවත යෙදෙන විට LINQ දෙකම කම්මැලි පැටවීමට උත්සාහ කරයි. (එක් එක් වර්ගය සඳහා අතුරු මුහුණත් දිගු කිරීමේ ක්‍රම මඟින් ක්‍රියාත්මක කිරීම දැකිය හැකි බව සලකන්න.)

වෙනත් වචන වලින් කිවහොත්, IEnumerablesතනිකරම "මතකයේ" නොවේ. IQueryablesසෑම විටම දත්ත සමුදායේ ක්‍රියාත්මක නොවේ. IEnumerableවියුක්ත දත්ත සැපයුම්කරුවෙකු නොමැති නිසා දේවල් මතකය වෙත පැටවිය යුතුය (නැවත ලබා ගත් පසු, සමහර විට කම්මැලි විය හැක). IQueryablesවියුක්ත සැපයුම්කරුවෙකු මත රඳා සිටින්න (LINQ-to-SQL වැනි), මෙය .NET මතක මතක සැපයුම්කරු විය හැකි වුවත්.

නියැදි භාවිත නඩුව

(අ) IQueryableEF සන්දර්භය අනුව වාර්තා ලැයිස්තුව ලබා ගන්න. (කිසිදු වාර්තාවක් මතකයේ නොමැත.)

(ආ) IQueryableආකෘතියක් ඇති දෘෂ්ටියකට යොමු කරන්න IEnumerable. (වලංගු. IQueryableදිගු වේ IEnumerable.)

(ඇ) දත්ත කට්ටලයේ වාර්තා, ළමා ආයතන සහ දේපල දෘෂ්ටියෙන් බැහැර කර ප්‍රවේශ වන්න. (ව්‍යතිරේක ඇති විය හැක!)

විය හැකි ගැටළු

(1) IEnumerableකම්මැලි පැටවීමේ උත්සාහයන් සහ ඔබේ දත්ත සන්දර්භය කල් ඉකුත්වී ඇත. සැපයුම්කරු තවදුරටත් නොමැති නිසා ව්‍යතිරේකය විසි කර ඇත.

(2) ආයතන රාමු ආයතන ප්‍රොක්සි සක්‍රීය කර ඇත (පෙරනිමිය), ඔබ කල් ඉකුත් වූ දත්ත සන්දර්භයක් සමඟ අදාළ (අථත්‍ය) වස්තුවකට ප්‍රවේශ වීමට උත්සාහ කරයි. (1) ට සමාන වේ.

(3) බහු ක්‍රියාකාරී ප්‍රති ult ල කට්ටල (MARS). ඔබ වැඩි එල්ලාවල මහතා නම් IEnumerableදී foreach( var record in resultSet )වාරණ හා සමගාමීව ප්රවේශ කිරීමට උත්සාහ record.childEntity.childProperty, ඔබ නිසා දත්ත කට්ටලයක් හා සමගද ආයතනයක් දෙකම කම්මැලි පැටවීම සඳහා අඟහරු සමග අවසන් විය හැක. ඔබගේ සම්බන්ධතා නූල තුළ එය සක්‍රීය කර නොමැති නම් මෙය ව්‍යතිරේකයක් ඇති කරයි.

විසඳුමක්

  • සම්බන්ධතා නූල තුළ MARS සක්‍රීය කිරීම විශ්වාස කළ නොහැකි ලෙස ක්‍රියාත්මක වන බව මම සොයාගෙන ඇත. මාස් හොඳින් වටහාගෙන පැහැදිලිවම අපේක්‍ෂා නොකරන්නේ නම් එය වළක්වා ගන්නැයි මම ඔබට යෝජනා කරමි.

විමසීම් සහ ගබඩා resultList = resultSet.ToList() ප්‍රති results ල ක්‍රියාත්මක කිරීමෙන් ඔබේ ආයතන මතකයේ පවතින බව සහතික කිරීමේ වඩාත් සරලම ක්‍රමය මෙය බව පෙනේ.

ඔබ අදාළ ආයතන වෙත ප්‍රවේශ වන අවස්ථා වලදී, ඔබට තවමත් දත්ත සන්දර්භයක් අවශ්‍ය විය හැකිය. එක්කෝ එය එසේත් නැතිනම් ඔබේ ප්‍රොක්සි සහ පැහැදිලිවම Includeසම්බන්ධිත ආයතන අක්‍රීය කළ හැකිය DbSet.


10

“IEnumerable” සහ “IQueryable” අතර ඇති ප්‍රධාන වෙනස වන්නේ පෙරහන් තර්කනය ක්‍රියාත්මක වන ස්ථානයයි. එකක් සේවාදායකයාගේ පැත්තෙන් (මතකයේ) ක්‍රියාත්මක වන අතර අනෙක දත්ත ගබඩාවේ ක්‍රියාත්මක වේ.

උදාහරණයක් ලෙස, අපගේ දත්ත ගබඩාවේ පරිශීලකයෙකු සඳහා වාර්තා 10,000 ක් ඇති උදාහරණයක් සලකා බැලිය හැකි අතර, සක්‍රීය පරිශීලකයින් 900 ක් පමණක් යැයි කියමු, එබැවින් මේ අවස්ථාවේ දී අපි “IEnumerable” භාවිතා කරන්නේ නම් පළමුව එය වාර්තා 10,000 ක් මතකයේ පටවනු ලැබේ. ඉන්පසු එය සක්‍රීය පරිශීලකයින් 900 දෙනා වෙත ආපසු හරවන IsActive පෙරණය යොදයි.

අනෙක් අතට එකම අවස්ථාවක අප “IQueryable” භාවිතා කරන්නේ නම් එය සෘජුවම දත්ත සමුදායේ IsActive පෙරණය යොදන අතර එහි සිට සෘජුවම සක්‍රීය පරිශීලකයින් 900 දෙනා ආපසු එනු ඇත.


කාර්ය සාධනය අනුව ප්‍රශස්ත හා සැහැල්ලු බර කුමක්ද?
සිට්කෝර් සෑම්

Am සෑම් "IQueryable" වඩාත් ප්‍රශස්ත හා සැහැල්ලු බර අනුව වඩාත් කැමති වේ.
ටබීෂ් උස්මාන්

7

අපට දෙකම එකම ආකාරයකින් භාවිතා කළ හැකි අතර ඒවා ක්‍රියාකාරීත්වයේ වෙනස් වේ.

IQueryable ක්‍රියාත්මක වන්නේ දත්ත සමුදායට එරෙහිව කාර්යක්ෂමව පමණි. එයින් අදහස් කරන්නේ එය සම්පූර්ණ තෝරාගත් විමසුමක් නිර්මාණය කරන අතර අදාළ වාර්තා පමණක් ලබා ගන්නා බවයි.

උදාහරණයක් ලෙස, 'නිමල්' සමඟ ආරම්භ වන හොඳම ගනුදෙනුකරුවන් 10 දෙනා රැගෙන යාමට අපට අවශ්‍යය . මෙම අවස්ථාවේදී තෝරාගත් විමසුම ජනනය වේ select top 10 * from Customer where name like ‘Nimal%’.

නමුත් අපි IEnumerable භාවිතා කළේ නම්, විමසුම සමාන වන select * from Customer where name like ‘Nimal%’අතර ඉහළම දස දෙනා C # කේතීකරණ මට්ටමින් පෙරහන් කරනු ලැබේ (එය සියලු පාරිභෝගික වාර්තා දත්ත ගබඩාවෙන් ලබා ගෙන ඒවා C # වෙත යොමු කරයි).


6

පළමු හොඳ පිළිතුරු 2 ට අමතරව (ඩ්‍රයිස් සහ යාකොබ් විසින්):

IEnumerable අතුරුමුහුණත System.Collections නාම අවකාශයේ ඇත.

IEnumerable වස්තුව මතකයේ ඇති දත්ත සමූහයක් නිරූපණය කරන අතර මෙම දත්ත ඉදිරියට ගෙන යා හැක්කේ ඉදිරියට පමණි. IEnumerable වස්තුව නියෝජනය කරන විමසුම වහාම සහ සම්පූර්ණයෙන්ම ක්‍රියාත්මක වන බැවින් යෙදුමට ඉක්මනින් දත්ත ලැබේ.

විමසුම ක්‍රියාත්මක කළ විට, IEnumerable විසින් සියලු දත්ත පටවනු ලබන අතර, අපට එය පෙරීමට අවශ්‍ය නම්, පෙරීමම සේවාදායකයාගේ පැත්තෙන් සිදු කෙරේ.

IQueryable අතුරුමුහුණත System.Linq නාම අවකාශයේ පිහිටා ඇත.

IQueryable වස්තුව දත්ත සමුදායට දුරස්ථ ප්‍රවේශයක් සපයන අතර ආරම්භයේ සිට අවසානය දක්වා හෝ ප්‍රතිලෝම අනුපිළිවෙලින් දත්ත හරහා සැරිසැරීමට ඔබට ඉඩ සලසයි. විමසුමක් නිර්මාණය කිරීමේ ක්‍රියාවලියේදී, ආපසු ලබා දුන් වස්තුව IQueryable, විමසුම ප්‍රශස්ත වේ. එහි ප්‍රති As ලයක් ලෙස, එය ක්‍රියාත්මක කිරීමේදී අඩු මතකයක් පරිභෝජනය කරයි, ජාල කලාප පළල අඩුය, නමුත් ඒ සමඟම එය අසංඛ්‍යාත වස්තුවක් ලබා දෙන විමසුමකට වඩා තරමක් සෙමින් සැකසිය හැක.

තෝරාගත යුත්තේ කුමක්ද?

ඔබට ආපසු ලබා දුන් දත්ත සමූහය අවශ්‍ය නම්, උපරිම වේගය සපයන IEnumerable භාවිතා කිරීම වඩා හොඳය.

ඔබට සම්පූර්ණ දත්ත කට්ටලය අවශ්‍ය නොවන්නේ නම්, නමුත් පෙරහන් කළ දත්ත කිහිපයක් පමණක් නම්, IQueryable භාවිතා කිරීම වඩා හොඳය.


1

ඉහත කරුණු වලට අමතරව, ඔබ IQueryableඒ වෙනුවට භාවිතා කරන්නේ නම් ඔබට ව්‍යතිරේක ලබා ගත හැකි බව සටහන් කිරීම සිත්ගන්නා කරුණකි IEnumerable:

පහත නම් පහත සඳහන් දෑ හොඳින් ක්‍රියාත්මක productsවේ IEnumerable:

products.Skip(-4);

නම් කෙසේ වෙතත් productsයනු IQueryableලබන අතර, එය ඩී බී මේසයෙන් ප්රවේශ වාර්තා කිරීමට උත්සාහ කරනවා, එවිට මෙම දෝෂය කරන්නම්:

OFFSET වගන්තියක දක්වා ඇති ඕෆ්සෙට් .ණ නොවිය හැක.

මෙයට හේතුව පහත විමසුම ඉදිකරන ලදි:

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

සහ OFFSET හි negative ණ අගයක් තිබිය නොහැක.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.