LINK EF C#
От: ronik  
Дата: 30.03.15 13:39
Оценка:
Всем привет! Есть List<int> id = new List<int>(); со значениями,
{12, 13, 14, 15}
В БД есть поля HomeId и GuestId.
Нужно найти все записи совпадающие по парно с id из листа, т.е. HomeId=12 и GuestId=15,
На сколько я понимаю необходимо сделать запрос к БД через where. Примерно так db.Test.Where(i=>i.HomeId == id[0] && i.GuestId == id[1])...
Возникает вопрос как быть если размер List не известен?
Re: LINK EF C#
От: Sinix  
Дата: 30.03.15 13:55
Оценка:
Здравствуйте, ronik, Вы писали:

R>{12, 13, 14, 15}

R>Нужно найти все записи совпадающие по парно с id из листа, т.е. HomeId=12 и GuestId=15,

GuestId = 13 тогда уж. Чтобы сгруппировать по парам — http://stackoverflow.com/a/1290459/318263

Для самого запроса с ходу не вспомню. Any(...) емнип работать не будет, .Join() тоже. Можно перебирать лениво (тоже не сахар), или сгенерить ef sql и выполнять уже его.

Кто плотно работает с EF — поправляйте!
Re: LINK EF C#
От: RushDevion Россия  
Дата: 30.03.15 20:14
Оценка:
Проще всего, наверное, через PredicateBuilder.
Что-то вроде такого:
var idList = new List<int>();
var predicate = PredicateBuilder.False<YourEntity>();
for (var i = 0; i < idList.Count; i += 2)
{
    int captured = i;
    predicate = predicate.Or(x => x.HomeId == idList[captured] && x.GuestId == idList[captured + 1]);
}
var matches = db.YourEntities.AsQueryable().Where(predicate).ToArray();
Re: LINK EF C#
От: ronik  
Дата: 31.03.15 13:49
Оценка:
А что вы скажете на счёт этого:
db.Test.Where(p => id.Contains(p.GuestId) && id.Contains(p.HomeId))
Re[2]: LINK EF C#
От: Sinix  
Дата: 31.03.15 13:59
Оценка:
Здравствуйте, ronik, Вы писали:

R>А что вы скажете на счёт этого:

db.Test.Where(p => id.Contains(p.GuestId) && id.Contains(p.HomeId))


Что оно даст кучу ложных срабатываний.

Самый простой пример (предположим, что множества значений у столбцов не пересекаются, иначе всё совсем плохо )

id | GuestId | HomeId
 0 |       1 |      2
 1 |       3 |      2
 2 |       3 |      4


фильтр: { 1, 4, 3, 2 }

По вашему запросу выберутся все строки, хотя в выборку должна попасть только вторая запись.
Re[2]: LINK EF C#
От: Danchik Украина  
Дата: 31.03.15 15:11
Оценка:
Здравствуйте, ronik, Вы писали:

R>А что вы скажете на счёт этого:

R>
R>db.Test.Where(p => id.Contains(p.GuestId) && id.Contains(p.HomeId))
R>


Так навскидку, что первое попалось
Внизу OrTheseFiltersTogether

http://stackoverflow.com/questions/4391044/dynamic-linq-or-conditions
Re: LINK EF C#
От: IT Россия linq2db.com
Дата: 31.03.15 18:20
Оценка: 72 (4)
Здравствуйте, ronik, Вы писали:

R>Всем привет! Есть List<int> id = new List<int>(); со значениями,

R>{12, 13, 14, 15}

Не скажу за EF, а на linq2db можно так:

using (var db = new DataConnection())
{
    var arr  = new[] { 11, 12, 13, 14 };
    var list =
        from i in Enumerable.Range(0, arr.Length / 2)
        select new { HomeId = arr[i * 2], GuestId = arr[i * 2 + 1] };

    var q =
        from t in db.GetTable<Table1>()
        where list.Contains(new { t.HomeId, t.GuestId })
        select t;

    q.ToList();
}
Если нам не помогут, то мы тоже никого не пощадим.
Отредактировано 31.03.2015 19:47 IT . Предыдущая версия .
Re: LINK EF C#
От: TK Лес кывт.рф
Дата: 01.04.15 06:31
Оценка:
Здравствуйте, ronik, Вы писали:

R>Возникает вопрос как быть если размер List не известен?


Размер List всегда есть в List.Count
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: LINK EF C#
От: ronik  
Дата: 01.04.15 06:59
Оценка: -1 :)
Здравствуйте, TK, Вы писали:

TK>Здравствуйте, ronik, Вы писали:


R>>Возникает вопрос как быть если размер List не известен?


TK>Размер List всегда есть в List.Count


Не, ну это понятно... Вы уж совсем меня за новичка держите...
Re: LINK EF C#
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 01.04.15 22:18
Оценка: -1
Здравствуйте, ronik, Вы писали:

R>Возникает вопрос как быть если размер List не известен?


Ох, ну как-то так:
var id = new List<int> { 12, 13, 14, 15 };

// splitting into pairs
var pairs = from i in Enumerable.Range(0, id.Count / 2) select id[i * 2] + "_" + id[i * 2 + 1];

// querying
var query = db.Test.Where(t => pairs.Contains(t.HomeId.ToString() + "_" + t.GuestId.ToString()));


Понятно, что "размер List" не бесконечен, но вот у меня (на SQLExpress) дошло до 3000 элементов, и я не стал тестить дальше (устал ждать).
Отредактировано 01.04.2015 23:48 scale_tone . Предыдущая версия . Еще …
Отредактировано 01.04.2015 22:28 scale_tone . Предыдущая версия .
Re[2]: LINK EF C#
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 03.04.15 11:58
Оценка: 36 (1)
Здравствуйте, Sinix, Вы писали:

S>Для самого запроса с ходу не вспомню. Any(...) емнип работать не будет, .Join() тоже. Можно перебирать лениво (тоже не сахар), или сгенерить ef sql и выполнять уже его.


Join(), кстати, тоже работает (EF 6.1.3):

var pairs = from i in Enumerable.Range(0, id.Count / 2) select id[i * 2] + "_" + id[i * 2 + 1];
var query = db.Test.Join(pairs, te => te.HomeId.ToString() + "_" + te.GuestId.ToString(), i => i, (te, _) => te);


SELECT 
    [Extent1].[HomeId] AS [HomeId], 
    [Extent1].[GuestId] AS [GuestId]
    FROM  [dbo].[TestObjects] AS [Extent1]
    INNER JOIN  (SELECT 
        N'12_13' AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]
    UNION ALL
        SELECT 
        N'14_15' AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1] 
    ON 
        ( CAST( [Extent1].[HomeId] AS nvarchar(max)) + N'_' +  CAST( [Extent1].[GuestId] AS nvarchar(max))) = [UnionAll1].[C1]


Но значительно медленнее этого
Автор: scale_tone
Дата: 02.04.15
.
Re[3]: LINK EF C#
От: Sinix  
Дата: 03.04.15 12:08
Оценка: +1
Здравствуйте, scale_tone, Вы писали:

_>Join(), кстати, тоже работает (EF 6.1.3):

Угу, жить захочешь — и не так раскорячишься
Как я понял, топикстартеру всё-таки нужно решение для продакшна, а не армейским способом (в хорошем смысле).

Кстати, ещё вариант: Contains() по столбцу с большей селективностью и затем дофильтровать на клиенте.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.