有一种名为Product的实体类型是由实体框架生成的。
我写了这个问题
public IQueryable<Product> GetProducts(int categoryID)
{
return from p in db.Products
where p.CategoryID== categoryID
select new Product { Name = p.Name};
}
下面的代码抛出以下错误:
实体或复杂类型的Shop。产品不能构造在
LINQ到实体查询"
var products = productRepository.GetProducts(1).Tolist();
但是当我使用select p而不是select new Product {Name = p.Name};它工作正常。
如何执行自定义选择节?
为了回应另一个被标记为重复的问题(见这里),我根据Soren的答案想出了一个快速而简单的解决方案:
data.Tasks.AddRange(
data.Task.AsEnumerable().Select(t => new Task{
creator_id = t.ID,
start_date = t.Incident.DateOpened,
end_date = t.Incident.DateCLosed,
product_code = t.Incident.ProductCode
// so on...
})
);
data.SaveChanges();
注意:
这个解决方案只适用于Task类上有一个导航属性(外键)(这里称为“Incident”)。
如果你没有,你可以使用“AsQueryable()”其他发布的解决方案之一。
为了回应另一个被标记为重复的问题(见这里),我根据Soren的答案想出了一个快速而简单的解决方案:
data.Tasks.AddRange(
data.Task.AsEnumerable().Select(t => new Task{
creator_id = t.ID,
start_date = t.Incident.DateOpened,
end_date = t.Incident.DateCLosed,
product_code = t.Incident.ProductCode
// so on...
})
);
data.SaveChanges();
注意:
这个解决方案只适用于Task类上有一个导航属性(外键)(这里称为“Incident”)。
如果你没有,你可以使用“AsQueryable()”其他发布的解决方案之一。
您可以投射到匿名类型,然后从它投射到模型类型
public IEnumerable<Product> GetProducts(int categoryID)
{
return (from p in Context.Set<Product>()
where p.CategoryID == categoryID
select new { Name = p.Name }).ToList()
.Select(x => new Product { Name = x.Name });
}
编辑:因为这个问题引起了很多关注,所以我要讲得更具体一些。
你不能直接投射到模型类型中(EF限制),所以没有办法绕过这个。唯一的方法是投射到匿名类型(第一次迭代),然后投射到建模类型(第二次迭代)。
还请注意,当您以这种方式部分加载实体时,它们不能被更新,因此它们应该保持分离状态。
我从来没有完全理解为什么这是不可能的,这个帖子上的答案也没有给出强烈的反对理由(主要是关于部分加载的数据)。在部分加载状态下实体不能被更新,这是正确的,但是之后,该实体将被分离,因此不可能意外地尝试保存它们。
考虑一下我上面使用的方法:结果我们仍然有一个部分加载的模型实体。该实体已分离。
考虑以下(希望存在)可能的代码:
return (from p in Context.Set<Product>()
where p.CategoryID == categoryID
select new Product { Name = p.Name }).AsNoTracking().ToList();
这也可能导致分离实体的列表,因此我们不需要进行两次迭代。编译器会聪明地看到AsNoTracking()已经被使用,这将导致分离的实体,所以它可以允许我们这样做。但是,如果AsNoTracking()被省略,它可能会抛出与现在抛出的相同的异常,以警告我们需要对我们想要的结果足够具体。