如何在LINQ中将查询结果声明给实体

如何在LINQ中将查询结果声明给实体,linq,entity-framework-4,Linq,Entity Framework 4,我刚开始使用MS实体框架,但LINQ有以下问题。我会简化我的问题,让它更清楚;假设SQL Server数据库中有三个表: CustomerData(PK是CustomerId,该表还有大约二十列用于保存客户数据) CustomerData1(以一对一关系保存客户的一些数据) CustomerData2(还以一对一关系保存客户的一些数据) 我知道具有一对一关系的数据最好在同一个表中,但这是一些公司数据库,不可能更改原始表(因此我们所有的数据都应该在单独的表中) 现在,我想显示一个客户列表,其中

我刚开始使用MS实体框架,但LINQ有以下问题。我会简化我的问题,让它更清楚;假设SQL Server数据库中有三个表:

  • CustomerData(PK是CustomerId,该表还有大约二十列用于保存客户数据)
  • CustomerData1(以一对一关系保存客户的一些数据)
  • CustomerData2(还以一对一关系保存客户的一些数据)
我知道具有一对一关系的数据最好在同一个表中,但这是一些公司数据库,不可能更改原始表(因此我们所有的数据都应该在单独的表中)

现在,我想显示一个客户列表,其中包含CustomerData表中的数据,并通过join从CustomerData1添加一些数据列。 另一方面,我想显示一个客户列表,并通过join从另一个表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
var query3=。选择(f=>newcustomer{
Id=f.obj.CustomerId,
Name=f.obj.CustomerName,
…Customer表中的其他列(很多)
//然后根据输入参数添加一些附加列
Data1=f.rel.someDataFromCustomer1,//仅当firstList==true时,否则为空
Data2=f.rel.someDataFromCustomer2//仅当secondList==true时,否则为空
}).OrderBy(f=>f.Name)//按客户名称订购
当然这不会编译,因为两个变量都在if语句中。我知道我可以将最后一条语句(var query3=…)复制到两个if语句中,并且只包括相关的赋值(Data1或Data2),但我不想将映射到CustomerData表的属性赋值两次(在两个if语句中都赋值一次),也不想排序两次


我怎样才能解决这个问题?我使用的是.NET 4。

您不能预先为匿名类型声明变量,即在两个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);
IQueryable resultQuery=null;
如果(第一名单)
{
resultQuery=来自CustomerData中的obj
在CustomerData1中加入rel
在obj.CustomerId上等于rel.CustomerId
选择新建ProjectedCustomerData
{
CustomerData=obj,
CustomerData1=rel
};
}
如果(第二名单)
{
resultQuery=来自CustomerData中的obj
在CustomerData2中加入rel
在obj.CustomerId上等于rel.CustomerId
选择新建ProjectedCustomerData
{
CustomerData=obj,
CustomerData2=rel
};
}
var query3=resultQuery.Select(f=>newcustomer{
Id=f.CustomerData.CustomerId,
Name=f.CustomerData.CustomerName,
// ...
Data1=f.CustomerData1.someDataFromCustomer1,
数据2=f.CustomerData2.someDataFromCustomer2
}).OrderBy(f=>f.Name);

我不确定
Customer
是您模型中的一个实体,还是仅用于投影的一个类。如果它是一个实体,您必须更改最后一个代码,因为您无法投影到一个实体中(基本上您需要另一个助手类型进行投影)。

您不能预先为匿名类型声明变量,即在两个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);
IQueryable resultQuery=null;
如果(第一名单)
{
resultQuery=来自CustomerData中的obj
在CustomerData1中加入rel
在obj.CustomerId上等于rel.CustomerId
选择新建ProjectedCustomerData
{
CustomerData=obj,
CustomerData1=rel
};
}
如果(第二名单)
{
resultQuery=来自CustomerData中的obj
在CustomerData2中加入rel
在obj.CustomerId上等于rel.CustomerId
选择新建ProjectedCustomerData
{
CustomerData=obj,
CustomerData2=rel
};
}
var query3=resultQuery.Select(f=>newcustomer{
Id=f.CustomerData.CustomerId,
Name=f.CustomerData.CustomerName,
// ...
Data1=f.CustomerData1.someDataFromCustomer1,
数据2=f.CustomerData2.someDataFromCustomer2
}).OrderBy(f=>f.Name);
我不确定
Customer
是您模型中的一个实体,还是仅用于投影的一个类。如果它是一个实体,你必须改变它