Тот же запрос LINQ с использованием объединений, но с разными условиями

У меня есть очень похожие LINQ-запросы:

var city = "Hamburg";

var query1 = 
    from c in DB.Customers
    join address in DB.Addresses on c.ID equals address.CustomerID
    where address.City == city
    select c;

var query2 = 
    from c in DB.Customers
    join address in DB.Addresses on c.ID equals address.CustomerID
    where address.City.StartsWith(city)
    select c;

etc.

Я хочу использовать цикл для создания запросов для уменьшения избыточности:

var city = "Hamburg";

var expressions = new Expression>[] {
    a => a == city,
    a => a.StartsWith(city)
};

for(int i = 1; i <= 2; i++) {
    queries.Add(
        from c in DB.Customers
        join address in DB.Addresses on c.ID equals address.CustomerID
        where expressions[i](address.City) 
        select c
        );
}

Но я не знаю, как создать массив выражений. Есть идеи?

4
nl ja de
с выражением >?
добавлено автор tschmit007, источник
@asawyer, только если вы предполагаете, что за EF существует db, совместимый с хранимой процедурой, а что же SQLite?
добавлено автор tschmit007, источник
Каков ваш ожидаемый результат? Один список, i список?
добавлено автор Hogan, источник
В стороне: в EF, join почти никогда не требуется. У вас нет свойства навигации, например Customer.Addresses ?
добавлено автор Nicholas Butler, источник
Честно говоря, это похоже на работу хранимой процедуры.
добавлено автор asawyer, источник
@Hogan Я ожидаю списки i , которые содержат клиентов, которые фильтруются различными выражениями.
добавлено автор Dennis, источник
Я уточнил вопрос с дополнительной информацией.
добавлено автор Dennis, источник
Спасибо за вашу помощь. Ответы Ли, Тилака также кажутся тем, что я хочу. Но мне нужно было выбрать один ответ, и я думаю, что ответ лазиберовского лучше всего соответствует моему примеру.
добавлено автор Dennis, источник

4 ответы

var city = "Hamburg";

// predicate should accept Address
var expressions = new Expression>[] {
    a => a.City == city,
    a => a.City.StartsWith(city)
};

foreach(var predicate in expressions) {
    queries.Add(
        DB.Customers.Join(
           DB.Addresses.Where(predicate),//filtering here
           c => c.ID, 
           a => a.CustomerID, 
           (c, a) => c)//return customer
    ));
}
3
добавлено

Вы можете использовать метод Join напрямую, а не использовать синтаксис запроса:

public IQueryable FindCustomers(Expression> predicate)
{
    return DB.Customers.Join(DB.Addresses, c => c.ID, a => d.CustomerID, (c, a) => new { Address = a, Customer = c})
        .Where(pair => predicate(pair.Address))
        .Select(pair => pair.Customer)
}

или вы можете передать как Customer , так и Address :

public IQueryable FindCustomers(Expression> predicate)
{
    return DB.Customers.Join(DB.Addresses, c => c.ID, a => d.CustomerID, (c, a) => new { Address = a, Customer = c})
        .Where(pair => predicate(pair.Customer, pair.Address))
        .Select(pair => pair.Customer)
}

то вы можете создать свой массив как:

IQueryable[] queries = expressions.Select(expr => FindCustomers(expr)).ToArray();
3
добавлено
предикат должен принять адрес
добавлено автор Sergey Berezovskiy, источник
@Dennis - я изменил его, чтобы использовать Address вместо Customer .
добавлено автор Lee, источник
Проблема заключается в том, что предикат должен получить доступ к свойству адреса, но когда я присоединяюсь к (c, a) => c , я могу использовать клиента только в своем предикате, или я что-то упускаю?
добавлено автор Dennis, источник
Вы правы, это нужно делать.
добавлено автор Dennis, источник

Вы можете сохранить общую часть соединения в общем запросе.

var query = from c in DB.Customers
         join address from DB.Addresses on c.ID equals address.CustomerID
         select new {A=a, C=c};
var query1 = query.Where ( item => item.A.temp == item.C.test).Select (item => item.C);
var query2 = query.Where ( item => item.A.temp2 == item.C.test2).Select (item => item.C);
1
добавлено
var queries=(
    from f in
        new Func[] { 
            x => x.City==city, 
            x => x.City.StartsWith(city)
            }
    select
        from c in DB.Customers
        join address in DB.Addresses on c.ID equals address.CustomerID
        where f(address)
        select c
    ).ToArray();
  1. You are creating an expression array, that means you are resulting an expression array after all; you don't need to make delegates an expression array.

  2. You don't need foreach

  3. If you will later add more expressions to queries, then change ToArray() to ToList()

  4. If You want to make Func be modified before you generate the queries, then define a local variable for it, and just replace the Func[]

1
добавлено
+1 - 100% linqy
добавлено автор Hogan, источник
Спасибо. Что такое Association Bonus , я только что получил это уведомление.
добавлено автор Ken Kin, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot