У меня есть список, содержащий ID и#39;ы в моя папка
таблицы. Как я могу выбрать все пользовательских профилей на основе список id's я попал в
ВАР, используя
в LINQ`?
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(......);
Я застрял прямо здесь. Я могу сделать это с помощью циклов for и т. д. Но я'лучше сделать это с помощью LINQ`.
Вы можете использовать содержит()
для этого. Он будет чувствовать себя немного назад, когда вы'вновь действительно стараются выпускать в
предложении, но это должно сделать это:
var userProfiles = _dataContext.UserProfile
.Where(t => idList.Contains(t.Id));
Я'м также при условии, что каждый профиль пользователя
запись будет инт
поле идентификатор
. Если это's не так, вы'придется корректировать.
Решение .Где и .Содержит имеет сложность o(n в квадрате). Простой .Присоединиться должны иметь намного лучше, производительность (близко к O(N) в результате хэширования). Так что правильный код:
_dataContext.UserProfile.Join(idList, up => up.ID, id => id, (up, id) => up);
А теперь результат моих измерений. Я сгенерировал 100 000 пользовательских профилей и 100 000 идентификаторов. Присоединяйтесь взял и 32ms .Где со .Содержит заняло 2 минуты и 19 секунд! Я использовал чистый интерфейс IEnumerable для этого испытания, чтобы доказать мое утверждение. Если вы используете список, а не возвращает, .Где и .Содержит будет быстрее. В любом случае разница существенная. Самый быстрый .Где .Содержит комплект<>. Все это зависит от сложности базовых coletions для .Содержит. Посмотри на этот пост, чтобы узнать о сложности технологии LINQ.Посмотрите на мой образец теста ниже:
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<int> GenerateIds()
{
// var result = new List<int>();
for (int i = 100000; i > 0; i--)
{
yield return i;
}
}
private static IEnumerable<UserProfile> GenerateUserProfiles()
{
for (int i = 0; i < 100000; i++)
{
yield return new UserProfile {ID = i};
}
}
Вывод на консоль:
прошедшее .Присоединиться время: 00:00:00.0322546
прошедшее .Где .Содержит время: 00:02:19.4072107
Хорошие ответы выше, но Дон'т забыть, что один важно вещь - они дают разные результаты!
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 строки из БД (и это может быть правильным, если вы просто хотите, особым отсортированный список пользователей)
Но во многих случаях вы можете хотите неразобранные список результатов. Вы всегда должны думать о нем, как о SQL-запроса. Пожалуйста, см. пример с интернет-магазин корзина для иллюстрации того, что'ы происходит:
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 результаты из БД. Использование 'содержит' хотелось бы ошибаться в этом случае.
Что должно быть простым. Попробуйте это:
var idList = new int[1, 2, 3, 4, 5];
var userProfiles = _dataContext.UserProfile.Where(e => idList.Contains(e));