Абярыце некалькі запісаў на аснове спісу ідэнтыфікатараў з дапамогай LINQ

У мяне ёсць спіс, які змяшчае ідэнтыфікатары майго UserProfile табліцы. Як я магу выбраць усе UserProfiles на аснове спісу ідэнтыфікатараў я атрымаў у вар выкарыстоўваючы LINQ ?

var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(......);

Я затрымаўся тут. Я магу зрабіць гэта, выкарыстоўваючы для завес і г.д. Але я хацеў бы зрабіць гэта з дапамогай LINQ .

86
задаць пытанне стаіць больш часу, чым рабіць пошук. у наступны раз толькі выказаць здагадку «ён/яна» зрабіў пошук або 10.
дададзена аўтар Yustme, крыніца
задаць пытанне стаіць больш часу, чым рабіць пошук. у наступны раз толькі выказаць здагадку «ён/яна» зрабіў пошук або 10.
дададзена аўтар Yustme, крыніца
пошук і выяўленне 2 розныя рэчы. Але так як вы можаце глядзець праз маё плячо, хоць у Інтэрнэце, не маглі б вы сказаць мне, як вы ведаеце, я не шукаў? чакаць не кажы! Вы бачылі, ці правільна гэта? мой пункт дакладна.
дададзена аўтар Yustme, крыніца
Гэта ўсё яшчэ атрымлівае зусім няшмат увагі, таму я думаў, я хацеў бы згадаць, што ReSharper робіць вельмі добрую працу прапаноўваючы месца, дзе вы маглі б ператварыць паўтаральны код у аператары LINQ. Для пачаткоўцаў у LINQ гэта можа быць незаменным інструментам мець толькі па гэтай мэты.
дададзена аўтар Yuck, крыніца
Гэта ўсё яшчэ атрымлівае зусім няшмат увагі, таму я думаў, я хацеў бы згадаць, што ReSharper робіць вельмі добрую працу прапаноўваючы месца, дзе вы маглі б ператварыць паўтаральны код у аператары LINQ. Для пачаткоўцаў у LINQ гэта можа быць незаменным інструментам мець толькі па гэтай мэты.
дададзена аўтар Yuck, крыніца

6 адказы

Вы можаце выкарыстоўваць Утрымоўвае() для гэтага. Ён будзе адчуваць сябе крыху назад, калі вы на самой справе спрабуеце вырабіць IN пункт, але гэта павінна зрабіць гэта:

var userProfiles = _dataContext.UserProfile
                               .Where(t => idList.Contains(t.Id));

Я таксама мяркую, што кожны UserProfile запіс будзе мець Int Id полі. Калі гэта не так, вы павінны наладзіць адпаведным чынам.

147
дададзена
Прывітанне, ды UserProfile запісу ўтрымліваюць ідэнтыфікатары. Так ці інакш я буду рабіць нешта накшталт т => t.id == idList.Contains (ідэнтыфікатар)?
дададзена аўтар Yustme, крыніца
Ну праблема ў тым, што т змяшчае ўвесь аб'ект UserProfile і список_идентификаторы ўтрымліваюць толькі INT-х. Кампілятар скардзіўся нешта, але я ўжо паспеў выправіць. Дзякуючы.
дададзена аўтар Yustme, крыніца
<�Код> Утрымоўвае() будзе апрацоўваць гэтую праверку роўнасці на кожным ID значэнне, калі вы выкарыстоўваеце яго, як я ўжо пісаў у адказ. Вам не трэба відавочна напісаць == у любым месцы, калі вы спрабуеце параўнаць элементы аднаго мноства (масіў) па адносінах да іншай (табліца базы дадзеных).
дададзена аўтар Yuck, крыніца
@Yuck - не працуе для мяне, кажа Функцыя тайм-аўт! У вас адключаны адкладзенай загрузкі, але да гэтага часу не ўдаецца.
дададзена аўтар bhuvin, крыніца

Вы можаце выкарыстоўваць Утрымоўвае() для гэтага. Ён будзе адчуваць сябе крыху назад, калі вы на самой справе спрабуеце вырабіць IN пункт, але гэта павінна зрабіць гэта:

var userProfiles = _dataContext.UserProfile
                               .Where(t => idList.Contains(t.Id));

Я таксама мяркую, што кожны UserProfile запіс будзе мець Int Id полі. Калі гэта не так, вы павінны наладзіць адпаведным чынам.

147
дададзена
Прывітанне, ды UserProfile запісу ўтрымліваюць ідэнтыфікатары. Так ці інакш я буду рабіць нешта накшталт т => t.id == idList.Contains (ідэнтыфікатар)?
дададзена аўтар Yustme, крыніца
Ну праблема ў тым, што т змяшчае ўвесь аб'ект UserProfile і список_идентификаторы ўтрымліваюць толькі INT-х. Кампілятар скардзіўся нешта, але я ўжо паспеў выправіць. Дзякуючы.
дададзена аўтар Yustme, крыніца
<�Код> Утрымоўвае() будзе апрацоўваць гэтую праверку роўнасці на кожным ID значэнне, калі вы выкарыстоўваеце яго, як я ўжо пісаў у адказ. Вам не трэба відавочна напісаць == у любым месцы, калі вы спрабуеце параўнаць элементы аднаго мноства (масіў) па адносінах да іншай (табліца базы дадзеных).
дададзена аўтар Yuck, крыніца
@Yuck - не працуе для мяне, кажа Функцыя тайм-аўт! У вас адключаны адкладзенай загрузкі, але да гэтага часу не ўдаецца.
дададзена аўтар bhuvin, крыніца

Рашэнне з .гдом і .Contains мае складанасць O (N квадрат). Просты .join павінен мець значна больш высокую прадукцыйнасць (блізка да O (N) з-за хэшавання). Такім чынам, правільны код:

_dataContext.UserProfile.Join(idList, up => up.ID, id => id, (up, id) => up);

And now result of my measurement. I generated 100 000 UserProfiles and 100 000 ids. Join took 32ms and .Where with .Contains took 2 minutes and 19 seconds! I used pure IEnumerable for this testing to prove my statement. If you use List instead of IEnumerable, .Where and .Contains will be faster. Anyway the difference is significant. The fastest .Where .Contains is with Set<>. All it depends on complexity of underlying coletions for .Contains. Look at this post to learn about linq complexity.Look at my test sample below:

    private static void Main(string[] args)
    {
        var userProfiles = GenerateUserProfiles();
        var idList = GenerateIds();
        var stopWatch = new Stopwatch();
        stopWatch.Start();
        userProfiles.Join(idList, up => up.ID, id => id, (up, id) => up).ToArray();
        Console.WriteLine("Elapsed .Join time: {0}", stopWatch.Elapsed);
        stopWatch.Restart();
        userProfiles.Where(up => idList.Contains(up.ID)).ToArray();
        Console.WriteLine("Elapsed .Where .Contains time: {0}", stopWatch.Elapsed);
        Console.ReadLine();
    }

    private static IEnumerable GenerateIds()
    {
      //var result = new List();
        for (int i = 100000; i > 0; i--)
        {
            yield return i;
        }
    }

    private static IEnumerable GenerateUserProfiles()
    {
        for (int i = 0; i < 100000; i++)
        {
            yield return new UserProfile {ID = i};
        }
    }

Кансольны выснова:

<�Р> Якое прайшло .join час: 00: 00: 00,0322546      <�Р> Якое прайшло .где .Contains час: 00: 02: 19,4072107
64
дададзена
што не было б справядліва дрэнь, так як ён адказаў на пытанне пра тое, як гэта было прапанавана (без выканання ў выглядзе). Акрамя таго, я ўпэўнены, што Yuck (гледзячы на ​​яго рэпутацыі) даў бы мне такі ж адказ, як у вас, калі прадукцыйнасць была частка пытання. Хоць я даў вам +1 :-)
дададзена аўтар Yustme, крыніца
Ніца, тым не менш зрабіць мне цікава, што таймінгі будзе, калі List выкарыстоўваецца. +1
дададзена аўтар Yustme, крыніца
Вы можаце вярнуцца, што з нумарамі?
дададзена аўтар Yustme, крыніца
@Yustme - прадукцыйнасць <�я> заўсёды </я> разгляд. (Я не хачу быць «гэта павінна быць прынята адказваць» хлопец, але ...)
дададзена аўтар jleach, крыніца
Адказ на гэтае пытанне не будзе, верагодна, дасць падобны O (N * N) супраць O (N) паляпшэнне Linq2Sql або Linq2Entities што і пытанне/прыклад, які ён просіць. Пры выкананні ў звароце да базы дадзеных, Linq генеруе SQL з «далучыцца» або «у ()» пункт аўтаматычна, так што не O (N * N).
дададзена аўтар crokusek, крыніца
Я атрымліваю Лакальная паслядоўнасць не можа быць выкарыстаны ў LINQ для рэалізацый SQL аператараў запытаў, акрамя Змяшчае аператара. памылка пры выкарыстанні Linq2SQL DataContext.
дададзена аўтар Mayank Raichura, крыніца
Я адрэдагаваў мой адказ з маім вымярэннем.
дададзена аўтар David Gregor, крыніца
Добра, вось таймінгі вы зацікаўлены ў: Спіс ўзялі 13,1 секунды і HashSet ўзялі 0,7 мс! Так .где .Contains лепш толькі ў выпадку HashSet (калі .Contains мае складанасць O (1)). У іншых выпадках .join лепш
дададзена аўтар David Gregor, крыніца
@Yustme: Калі вам падабаецца мой адказ разам з усімі Measurment, вы можаце ўсталяваць як правільны адказ. Дзякуй :)
дададзена аўтар David Gregor, крыніца

Рашэнне з .гдом і .Contains мае складанасць O (N квадрат). Просты .join павінен мець значна больш высокую прадукцыйнасць (блізка да O (N) з-за хэшавання). Такім чынам, правільны код:

_dataContext.UserProfile.Join(idList, up => up.ID, id => id, (up, id) => up);

And now result of my measurement. I generated 100 000 UserProfiles and 100 000 ids. Join took 32ms and .Where with .Contains took 2 minutes and 19 seconds! I used pure IEnumerable for this testing to prove my statement. If you use List instead of IEnumerable, .Where and .Contains will be faster. Anyway the difference is significant. The fastest .Where .Contains is with Set<>. All it depends on complexity of underlying coletions for .Contains. Look at this post to learn about linq complexity.Look at my test sample below:

    private static void Main(string[] args)
    {
        var userProfiles = GenerateUserProfiles();
        var idList = GenerateIds();
        var stopWatch = new Stopwatch();
        stopWatch.Start();
        userProfiles.Join(idList, up => up.ID, id => id, (up, id) => up).ToArray();
        Console.WriteLine("Elapsed .Join time: {0}", stopWatch.Elapsed);
        stopWatch.Restart();
        userProfiles.Where(up => idList.Contains(up.ID)).ToArray();
        Console.WriteLine("Elapsed .Where .Contains time: {0}", stopWatch.Elapsed);
        Console.ReadLine();
    }

    private static IEnumerable GenerateIds()
    {
      //var result = new List();
        for (int i = 100000; i > 0; i--)
        {
            yield return i;
        }
    }

    private static IEnumerable GenerateUserProfiles()
    {
        for (int i = 0; i < 100000; i++)
        {
            yield return new UserProfile {ID = i};
        }
    }

Кансольны выснова:

<�Р> Якое прайшло .join час: 00: 00: 00,0322546      <�Р> Якое прайшло .где .Contains час: 00: 02: 19,4072107
64
дададзена
што не было б справядліва дрэнь, так як ён адказаў на пытанне пра тое, як гэта было прапанавана (без выканання ў выглядзе). Акрамя таго, я ўпэўнены, што Yuck (гледзячы на ​​яго рэпутацыі) даў бы мне такі ж адказ, як у вас, калі прадукцыйнасць была частка пытання. Хоць я даў вам +1 :-)
дададзена аўтар Yustme, крыніца
Ніца, тым не менш зрабіць мне цікава, што таймінгі будзе, калі List выкарыстоўваецца. +1
дададзена аўтар Yustme, крыніца
Вы можаце вярнуцца, што з нумарамі?
дададзена аўтар Yustme, крыніца
@Yustme - прадукцыйнасць <�я> заўсёды </я> разгляд. (Я не хачу быць «гэта павінна быць прынята адказваць» хлопец, але ...)
дададзена аўтар jleach, крыніца
Адказ на гэтае пытанне не будзе, верагодна, дасць падобны O (N * N) супраць O (N) паляпшэнне Linq2Sql або Linq2Entities што і пытанне/прыклад, які ён просіць. Пры выкананні ў звароце да базы дадзеных, Linq генеруе SQL з «далучыцца» або «у ()» пункт аўтаматычна, так што не O (N * N).
дададзена аўтар crokusek, крыніца
Я атрымліваю Лакальная паслядоўнасць не можа быць выкарыстаны ў LINQ для рэалізацый SQL аператараў запытаў, акрамя Змяшчае аператара. памылка пры выкарыстанні Linq2SQL DataContext.
дададзена аўтар Mayank Raichura, крыніца
Я адрэдагаваў мой адказ з маім вымярэннем.
дададзена аўтар David Gregor, крыніца
Добра, вось таймінгі вы зацікаўлены ў: Спіс ўзялі 13,1 секунды і HashSet ўзялі 0,7 мс! Так .где .Contains лепш толькі ў выпадку HashSet (калі .Contains мае складанасць O (1)). У іншых выпадках .join лепш
дададзена аўтар David Gregor, крыніца
@Yustme: Калі вам падабаецца мой адказ разам з усімі Measurment, вы можаце ўсталяваць як правільны адказ. Дзякуй :)
дададзена аўтар David Gregor, крыніца

Гэта павінна быць проста. Паспрабуйце гэта:

var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e));
12
дададзена

Добрыя адказы abowe, але не варта забываць адну Увага! рэчы - яны даюць розныя вынікі!

  var idList = new int[1, 2, 2, 2, 2];//same user is selected 4 times
  var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e)).ToList();

Гэта верне 2 радкі з БД (і гэта можа быць правільным, калі вы проста хочаце выразны адсартаваны спіс карыстальнікаў)

BUT in many cases, you could want an unsorted list of results. You always have to think about it like about a SQL query. Please see the example with eshop shopping cart to illustrate what's going on:

  var priceListIDs = new int[1, 2, 2, 2, 2];//user has bought 4 times item ID 2
  var shoppingCart = _dataContext.ShoppingCart
                     .Join(priceListIDs, sc => sc.PriceListID, pli => pli, (sc, pli) => sc)
                     .ToList();

Гэта будзе вяртаць 5 вынікі з БД. Выкарыстанне "ўтрымлiвае" было б няправільна ў гэтым выпадку.

9
дададзена