gpt4 book ai didi

c# - 单个 LINQ 中两个结构不兼容的初始化出错

转载 作者:行者123 更新时间:2023-12-03 16:20:44 26 4
gpt4 key购买 nike

我有一个下面的模型,当我使用下面的 linq 添加 ComboProducts 对象时,出现错误。这段代码中我缺少什么吗?
错误

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.


模型
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public List<Product> ComboProducts { get; set; }
}
代码
ListOfProducts = (
from p in db.Products
join ptp in db.ProductToProducts on p.ProductId equals ptp.ParentProductId
join pr in db.Pricings on ptp.ProductToProductId equals pr.ProductToProductId
where p.SubProductTypeId == (int)SubProductTypeId
select new Model.Product
{
ProductId = p.ProductId,
Name = p.Name,
PreviewUrl = p.PreviewURL,
ShortName = p.ShortName,
Description = p.Description,
PublicProduct = p.PublicProduct,
Price = pr.Price,
ComboProducts = (
from ptpx in db.ProductToProducts
join ap in db.Products on ptpx.ChildProductId equals ap.ProductId
where ptpx.ParentProductId == p.ProductId
select new Model.Product
{
Name = ap.Name,
ProductId = ap.ProductId
}
).OrderBy(p2 => p2.Name).ToList(),
DisplayOrder = p.DisplayOrder != null ? (int)p.DisplayOrder : 0
})
.GroupBy(grp => new
{
grp.ProductId
}
)
.Select(x => x.FirstOrDefault())
.ToList();

return ListOfProducts;

最佳答案

异常消息很清楚,你有两个 select new NCCN.Model.Product一个 LINQ 语句中不以相同顺序设置相同属性的语句。这是我们必须处理的 EF 限制。 LINQ-to-objects 不会抛出这个异常。
虽然你的问题不是很清楚,但我想我明白你实际上在问什么。即使在理解异常消息时,如何处理它也不是很明显。在指出问题之前,让我先介绍一个简化的模型。

public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }

public ICollection<ProductComponent> Components { get; set; }
}

public class ProductComponent
{
public int ProductId { get; set; }
public int ComponentProductId { get; set; }
public Product Product { get; set; }
public Product ComponentProduct { get; set; }
}
带映射代码。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ProductComponent>().HasKey(e => new { e.ProductId, e.ComponentProductId });
modelBuilder.Entity<ProductComponent>().HasRequired(e => e.Product)
.WithMany(p => p.Components).HasForeignKey(e => e.ProductId);
modelBuilder.Entity<ProductComponent>().HasRequired(e => e.ComponentProduct)
.WithMany().HasForeignKey(e => e.ComponentProductId)
.WillCascadeOnDelete(false); // Prevent circular cascade
}
现在我们可以使用导航属性而不是一直加入。
任务是将此模型映射到 DTO 类:
public class ProductDto
{
public int ProductId { get; set; }
public string Name { get; set; }
public List<ProductDto> ComboProducts { get; set; }
}
应该很简单
var products = db.Products.Select(p => new ProductDto
{
ProductId = p.ProductId,
Name = p.Name,
ComboProducts =
p.Components.Select(pc => pc.ComponentProduct)
.Select(c => new ProductDto
{
ProductId = c.ProductId,
Name = c.Name,
}).ToList()
});
但是现在EF抛出你报告的异常。在您的情况下,您甚至跳过了整个范围的属性,这里只有 ComboProducts在嵌套 ProductDto ,但这已经足够了。内部 ProductDto应该有一个 ComboProducts收藏也是。
不幸的是,这并不像人们期望的那样简单。例如,使用这个内部选择...
 .Select(c => new ProductDto
{
ProductId = c.ProductId,
Name = c.Name,
ComboProducts = null
}).ToList()
...EF throw

NotSupportedException: Unable to create a null constant value of type 'System.Collections.Generic.List`1[[ProductDto]]'. Only entity types, enumeration types or primitive types are supported in this context.


和...
 .Select(c => new ProductDto
{
ProductId = c.ProductId,
Name = c.Name,
ComboProducts = new List<ProductDto>()
}).ToList()
... throw

NotSupportedException: A type that implements IEnumerable 'System.Collections.Generic.List`1[[ProductDto]]' cannot be initialized in a LINQ to Entities query.


归结为:对于这样的嵌套投影,您必须对主要类型和嵌套类型使用两种不同的类型。但是匿名类型也符合要求,所以我认为解决这个恼人的 EF 限制的最简单方法是转换到匿名类型,然后转换到 ProductDto :
var products = db.Products.Select(p => new
{
ProductId = p.ProductId,
Name = p.Name,
ComboProducts =
p.Components.Select(pc => pc.ComponentProduct)
.Select(c => new
{
ProductId = c.ProductId,
Name = c.Name
}).ToList()
}).AsEnumerable() // Continue in memory so EF won't translate the following part
.Select(x => new ProductDto
{
ProductId = x.ProductId,
Name = x.Name,
ComboProducts = x.ComboProducts.Select(cp => new ProductDto
{
Name = cp.Name,
ProductId = cp.ProductId,
}).ToList()
}
).ToList();

关于c# - 单个 LINQ 中两个结构不兼容的初始化出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63059520/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com