Как объявить результат запроса в LINQ to Entities - PullRequest
1 голос
/ 15 октября 2011

Я только начал использовать MS Entity Framework, и у меня возникла следующая проблема с LINQ.Я упросту свою проблему, чтобы прояснить ее;скажем, у меня есть три таблицы в базе данных SQL Server:

  • CustomerData (PK - это CustomerId, таблица также содержит около двадцати столбцов для хранения данных о клиентах).
  • CustomerData1 (содержит некоторыеданные для клиента в отношении один к одному).
  • CustomerData2 (также содержит некоторые данные для клиента в отношении один к одному).

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

Теперь я хочу отобразитьсписок клиентов с их данными из таблицы CustomerData и добавление некоторых столбцов данных из CustomerData1 через соединение.С другой стороны, я хочу отобразить список клиентов и добавить некоторые данные из другой таблицы CustomerData2 через объединение.

Таким образом, данные в основном одинаковы оба раза, за исключением того, что в первом случае результат включает в себя некоторыестолбцы из CustomerData1 и во втором случае некоторые данные из таблицы CustomerData2.

Поэтому я создал класс Customer со свойствами для всех соответствующих столбцов в таблице CustomerData и добавил свойства для столбцов, которые должны быть включены из CustomerData1, и свойства, которые должныбыть включенным из CustomerData2.Все столбцы должны включаться каждый раз, за ​​исключением того, что при первом вызове свойства, сопоставляемые с таблицей CustomerData2, будут пустыми, а во время второго вызова свойства, сопоставляемые с таблицей CustomerData1, будут пустыми.

Для этогоЯ хотел создать одну функцию, поэтому я попытался создать ее следующим образом: входной параметр в функции - это то, включены ли данные из CustomerData1 или CustomerData2.

if (firstList)
{
  var query1 = from obj in CustomerData
               join rel in CustomerData1
               on obj.CustomerId equals rel.CustomerId 
               select new { obj, rel };
}

if (secondList)
{
   var query2 = from obj in CustomerData
               join rel in CustomerData2
               on obj.CustomerId equals rel.CustomerId 
               select new { obj, rel };
}

Так что этот код дает мне анонимный тип на основе вводапараметр.Теперь я хочу создать объекты Customer и заказать их (порядок всегда один и тот же, он не зависит от входного параметра).Поэтому я хочу создать список заказанных клиентов и включить дополнительные данные на основе входного параметра.

var query3 = <previous_query_variable>.Select(f => new Customer {
Id = f.obj.CustomerId,
Name = f.obj.CustomerName,
... other columns from Customer table (a lot of them)
//and then add some additional columns based on the input parameter
Data1 = f.rel.someDataFromCustomer1, //only when firstList == true, otherwise empty
Data2 = f.rel.someDataFromCustomer2  //only when secondList == true, otherwise empty
}).OrderBy(f => f.Name); //order by customer name

Конечно, это не компилируется, поскольку обе переменные находятся внутри операторов if.Я знаю, что могу скопировать этот последний оператор (var query3 = ...) внутри обоих операторов if и включить только соответствующие назначения (Data1 или Data2), но я не хочу назначать свойства, которые сопоставляются с таблицей CustomerData дважды (один раз в обоихесли заявления) ни я не хочу заказывать дважды.

Как я могу решить эту проблему?Я использую .NET 4.

1 Ответ

1 голос
/ 15 октября 2011

Невозможно заранее объявить переменную для анонимного типа, т. Е. Перед вашими двумя операторами if. (Что-то вроде var query = null не поддерживается.) Вам придется создать вспомогательный тип и спроецировать в него, например, так:

public class ProjectedCustomerData
{
    public CustomerData CustomerData { get; set; }
    public CustomerData1 CustomerData1 { get; set; }
    public CustomerData2 CustomerData2 { get; set; }
}

А потом проекция:

IQueryable<ProjectedCustomerData> resultQuery = null;
if (firstList)
{
    resultQuery = from obj in CustomerData
                  join rel in CustomerData1
                  on obj.CustomerId equals rel.CustomerId 
                  select new ProjectedCustomerData
                  {
                      CustomerData = obj,
                      CustomerData1 = rel
                  };
}
if (secondList)
{
    resultQuery = from obj in CustomerData
                  join rel in CustomerData2
                  on obj.CustomerId equals rel.CustomerId 
                  select new ProjectedCustomerData
                  {
                      CustomerData = obj,
                      CustomerData2 = rel
                  };
}

var query3 = resultQuery.Select(f => new Customer {
    Id = f.CustomerData.CustomerId,
    Name = f.CustomerData.CustomerName,
    // ...
    Data1 = f.CustomerData1.someDataFromCustomer1,
    Data2 = f.CustomerData2.someDataFromCustomer2
}).OrderBy(f => f.Name);

Я не уверен, является ли Customer сущностью в вашей модели или только классом, который вы используете для своей проекции. Если это сущность, вам нужно изменить последний код, потому что вы не можете проецировать в сущность (в основном вам потребуется другой тип помощника для проекции).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...