如何在LINQ to Entities中声明查询结果

时间:2011-10-15 10:17:13

标签: linq entity-framework-4

我刚刚开始使用MS实体框架,并且LINQ存在以下问题。我会简化我的问题,使其更清晰;假设我在SQL Server数据库中有三个表:

  • CustomerData(PK是CustomerId,该表还有大约20列来保存客户数据)。
  • CustomerData1(以一对一的关系为客户保留一些数据)。
  • CustomerData2(也以一对一的关系为客户保留一些数据)。

我知道具有一对一关系的数据应该更好地在同一个表中,但这是一些公司数据库,并且不可能改变原始表(所以我们所有的数据都应该在单独的表中)。 / p>

现在,我想显示一个客户列表及其来自CustomerData表的数据,并通过join从CustomerData1添加一些数据列。 另一方面,我想显示一个客户列表,并通过join从其他表CustomerData2添加一些数据。

所以数据基本上都是相同的,除了在第一种情况下结果包括来自CustomerData1的一些列,在第二种情况下包括来自CustomerData2表的一些数据。

因此,我使用CustomerData表中所有相关列的属性创建了Customer类,并添加了应包含在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语句中。我知道我可以在if语句中复制最后一个语句(var query3 = ...)并仅包含相关的赋值(Data1或Data2),但我不想分配映射到CustomerData表的属性两次(两次都是一次)如果声明)我也不想订购两次。

我该如何解决这个问题?我使用的是.NET 4。

1 个答案:

答案 0 :(得分:1)

您不能预先声明匿名类型的变量,即在两个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是模型中的实体还是仅用于投影的类。如果它是一个实体,你必须更改最后一个代码,因为你不能投射到一个实体(基本上你需要另一个帮助类型进行投影)。