LinqToSql: Как я могу создать проекцию, чтобы придерживаться DRY?

Просто интересно, есть ли способ вывести некоторые повторения из проецируемого типа LINQ to SQL.

Пример:

Таблица: адрес

Поля: AddressID, HouseNumber, Street, City, State, Zip и еще 20

Класс MyAddress: AddressID, HouseNumber, Street (только 3 поля)

LINQ:

from a in db.Addresses
select new MyAddress
{
  AddressID = a.AddressID,
  HouseNumber = a.HouseNumber,
  Street = a.Street
}

Приведенный выше запрос работает отлично, и я понимаю, почему что-то вроде этого вернет все 20+ полей в каждой строке:

from a in db.Addresses
select new MyAddress(a);

class MyAddress
{
  public MyAddress(Address a)
  {
    this.AddressID = a.AddressID,
    this.HouseNumber = a.HouseNumber,
    this.Street = a.Street
  }
}

Что приводит меня к моему вопросу:

Можно ли реализовать какую-то вспомогательную функцию или метод расширения для «сопоставления» модели LINQ с MyAddress, но возвращать в результате запроса только необходимые поля, а не все поля?


person Mike    schedule 09.04.2010    source источник
comment
Зачем вообще нужен сокращенный тип данных?   -  person Marcelo Cantos    schedule 09.04.2010
comment
Если я работаю с таблицей, в которой 20-30-40 полей, а мне нужно/хочу только 3, зачем SQL выполняет эту работу и возвращает все эти дополнительные данные по сети?   -  person Mike    schedule 09.04.2010


Ответы (1)


from a in db.Addresses
select new MyAddress
{
  AddressID = a.AddressID,
  HouseNumber = a.HouseNumber,
  Street = a.Street
}

Этот запрос выберет только запрошенные поля в результирующем SQL.

Функция для повторного использования типа будет выглядеть так:

public IQueryable<MyAddress> ProjectAddress(IQueryable<Address> addresses)
{
    return from a in addresses
           select new MyAddress
           {
               AddressID = a.AddressID,
               HouseNumber = a.HouseNumber,
               Street = a.Street
           };
}

Это можно использовать так:

return ProjectAddress(db.Addresses);

Я думаю, что функция будет выглядеть примерно так:

public static Expression<Func<Address, MyAddress>> ToMyAddress()
{
    return a => new MyAddress { AddressID = a.AddressID, 
                                HouseNumber = a.HouseNumber,
                                Street = a.Street
                              };
}
person Peter Willis    schedule 12.04.2010
comment
Похоже, что ключ IQueryable в качестве возвращаемого типа? Как насчет одного адреса? У меня есть объект с двумя свойствами: OriginalAddress и CurrentAddress, оба типа адреса. Можно ли создать вспомогательную функцию для принятия модели предметной области и выдачи модели представления? Все, что я пытаюсь сделать, приводит к извлечению всей записи из базы данных. Я слишком много пытаюсь реорганизовать? - person Mike; 13.04.2010
comment
Использование IQueryable означает, что linq останется выражением, на основе которого можно построить, которое позже преобразуется в запрос и выполняется. Я думаю, что понимаю, чего вы пытаетесь достичь: представить проекцию объекта адреса в модель представления адреса в виде кода и использовать это как вызов функции несколько раз в другой проекции. Это правильно? - person Peter Willis; 13.04.2010
comment
Ключевым моментом будет использование динамического linq и создание выражения, представляющего преобразование. ИМХО Я бы сказал, что получившийся код будет выглядеть довольно сложным для тех, кто не знаком с созданием выражений и метапрограммированием. Тем не менее, это определенно увеличит значение DRY. Я бы сделал суждение и сказал, что если я повторяю код в значительном количестве мест, и изменение этого кода займет значительное количество времени, тогда действуйте. - person Peter Willis; 13.04.2010
comment
Я внес правку в ответ. Как вы думаете, это слишком далеко? - person Peter Willis; 13.04.2010