从联接映射 - 类型 'CarDTO' 出现在单个 LINQ to Entities 查询中的两个结构上不兼容的初始化中
Mapping from join - The type 'CarDTO' appears in two structurally incompatible initializations within a single LINQ to Entities query
我试图从 left join
的右侧映射到 CarDTO
,但出现以下错误:
The type 'CarDTO' appears in two structurally incompatible
initializations within a single LINQ to Entities query. A type can be
initialized in two places in the same query, but only if the same
properties are set in both places and those properties are set in the
same order.
我正在尝试 self left join
,我的查询如下所示:
var query = from left in db.Cars
join right in db.Cars on left.id_Base equals right.ID into rightGrouped
from rightGr in rightGrouped.DefaultIfEmpty()
select new CarDTO()
{
ID = left.ID,
Description = left.DisplayName,
Name = left.Name,
IsSystem = left != null ? left.Template.isSystem : (byte?)null,
IdBase = left.id_Base,
InnerCar = new CarDTO()
{
ID = rightGr.ID,
Description = rightGr.DisplayName,
Name = rightGr.Name,
IsSystem = rightGr != null ? rightGr.Template.isSystem : (byte?)null,
IdBase = rightGr.id_Base,
InnerCar = new CarDTO()
}
};
如果我将下一行 InnerCar = new CarDTO()
更改为 InnerCar = null
,
然后我收到以下错误:
Unable to create a null constant value of type 'CarDTO'. Only entity
types, enumeration types or primitive types are supported in this
context.`
有人知道我做错了什么吗?
错误消息解释说 EF 期望同一表达式中所有相同类型的初始化(在本例中为 CarDto
)遵循一个规则:在每个初始化中应该设置相同的属性,并且在相同的表达式中命令。您的代码违反了这条规则,因为您有 3 次初始化。其中 2 个以相同的顺序设置相同的属性,但第三个(最后一个 InnerCar = new CarDTO()
)没有。
在 InnerCar.InnerCar
初始化中满足此规则的唯一可能值是 null
(因为递归定义)。但是,EF 不允许您这样做,因为它无法创建任意类型的常量值(不知道如何将此类东西转换为 SQL)。
所以用递归类型做这个是不可能的。相反,我们应该为 InnerCar
使用不同的类型。这可以通过匿名类型来完成:
select new
{
ID = left.ID,
Description = left.DisplayName,
Name = left.Name,
IsSystem = left != null ? left.Template.isSystem : (byte?)null,
IdBase = left.id_Base,
InnerCar = new
{
ID = rightGr.ID,
Description = rightGr.DisplayName,
Name = rightGr.Name,
IsSystem = rightGr != null ? rightGr.Template.isSystem : (byte?)null,
IdBase = rightGr.id_Base
}
};
这会起作用,因为这里的两个匿名类型是不同的。第一个有 6 个属性(包括 InnerCar
),第二个有 5 个属性(没有 InnerCar
)。当然这里不要求类型是匿名的。
你也可以将这个结构展平:
select new
{
LeftID = left.ID,
RightID = rightGr.ID,
// etc
};
执行此类映射并完成任何其他映射后 filtering\paging\whatever - 实现后将其转换为您的类型:
// query here is complete
var result = query.AsEnumerable().Select(c => {
new CarDto {
ID = c.ID,
Description = c.Description,
// etc
}
});
我试图从 left join
的右侧映射到 CarDTO
,但出现以下错误:
The type 'CarDTO' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.
我正在尝试 self left join
,我的查询如下所示:
var query = from left in db.Cars
join right in db.Cars on left.id_Base equals right.ID into rightGrouped
from rightGr in rightGrouped.DefaultIfEmpty()
select new CarDTO()
{
ID = left.ID,
Description = left.DisplayName,
Name = left.Name,
IsSystem = left != null ? left.Template.isSystem : (byte?)null,
IdBase = left.id_Base,
InnerCar = new CarDTO()
{
ID = rightGr.ID,
Description = rightGr.DisplayName,
Name = rightGr.Name,
IsSystem = rightGr != null ? rightGr.Template.isSystem : (byte?)null,
IdBase = rightGr.id_Base,
InnerCar = new CarDTO()
}
};
如果我将下一行 InnerCar = new CarDTO()
更改为 InnerCar = null
,
然后我收到以下错误:
Unable to create a null constant value of type 'CarDTO'. Only entity types, enumeration types or primitive types are supported in this context.`
有人知道我做错了什么吗?
错误消息解释说 EF 期望同一表达式中所有相同类型的初始化(在本例中为 CarDto
)遵循一个规则:在每个初始化中应该设置相同的属性,并且在相同的表达式中命令。您的代码违反了这条规则,因为您有 3 次初始化。其中 2 个以相同的顺序设置相同的属性,但第三个(最后一个 InnerCar = new CarDTO()
)没有。
在 InnerCar.InnerCar
初始化中满足此规则的唯一可能值是 null
(因为递归定义)。但是,EF 不允许您这样做,因为它无法创建任意类型的常量值(不知道如何将此类东西转换为 SQL)。
所以用递归类型做这个是不可能的。相反,我们应该为 InnerCar
使用不同的类型。这可以通过匿名类型来完成:
select new
{
ID = left.ID,
Description = left.DisplayName,
Name = left.Name,
IsSystem = left != null ? left.Template.isSystem : (byte?)null,
IdBase = left.id_Base,
InnerCar = new
{
ID = rightGr.ID,
Description = rightGr.DisplayName,
Name = rightGr.Name,
IsSystem = rightGr != null ? rightGr.Template.isSystem : (byte?)null,
IdBase = rightGr.id_Base
}
};
这会起作用,因为这里的两个匿名类型是不同的。第一个有 6 个属性(包括 InnerCar
),第二个有 5 个属性(没有 InnerCar
)。当然这里不要求类型是匿名的。
你也可以将这个结构展平:
select new
{
LeftID = left.ID,
RightID = rightGr.ID,
// etc
};
执行此类映射并完成任何其他映射后 filtering\paging\whatever - 实现后将其转换为您的类型:
// query here is complete
var result = query.AsEnumerable().Select(c => {
new CarDto {
ID = c.ID,
Description = c.Description,
// etc
}
});