ASPNET MVC5网络应用
在获取与其他实体的关系由以下模型描述的产品时,我只需要过滤那些language_id等于文化参数的Products.Category.CategoryTrans。
请注意我需要将结果作为IQueryable传递给已经实现的后续分页和排序方法。
型号:
public partial class Product
{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDeleted { get; set; }
public bool IsApproved { get; set; }
public int CategoryID { get; set; }
public virtual Category Category { get; set; }
[NotMapped]
public virtual CategoryTrans CategoryTrans { get; set; }
}
public partial class Category
{
public int ID { get; set; }
public string Name { get; set; }
public int? ParentID { get; set; }
public bool IsDeleted { get; set; }
public virtual ICollection<Product> Products { get; set; }
public virtual ICollection<CategoryTrans> CategoryTrans { get; set; }
}
public class ISO_Languages
{
public int ID { get; set; }
public string code { get; set; }
public bool IsEnabled { get; set; }
public string name_en { get; set; }
public string name_fr { get; set; }
public string name_it { get; set; }
public string name_de { get; set; }
public string name_es { get; set; }
}
public class CategoryTrans
{
[Key, Column(Order = 1)]
public int category_id { get; set; }
[Key, Column(Order = 2)]
public int language_id { get; set; }
[ForeignKey("category_id")]
public virtual Category categoryId { get; set; }
[ForeignKey("language_id")]
public virtual ISO_Languages languageId { get; set; }
public string name { get; set; }
}
以下查询返回p.Category.CategoryTrans中的所有CategoryTrans,这意味着任何类别翻译
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = (from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select p);
return query;
}
我要做的是根据文化输入参数为每个产品过滤单一类别翻译。 类似的东西:
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).SingleOrDefault()
};
return query;
}
但收到错误:
无法在LINQ to Entities查询中构造实体或复杂类型“xyz.DAL.Product”。
正在寻找这个特定错误,我现在尝试投影到DTO:
public class ProductDTO
{
public int? ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual CategoryTrans CategoryTrans { get; set; }
}
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db, string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture
select new ProductDTO
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).FirstOrDefault()
};
return query.Cast<Product>();
}
现在正在按预期工作,只返回到CategoryTrans所需的翻译。 因此查询现在可以工作但是将ProductDTO转换为所需的产品返回:
无法将类型'xyz.Controllers.ProductDTO'强制转换为'xyz.Models.Product'类型。 LINQ to Entities仅支持转换EDM原语或枚举类型。
我无法找到此异常的解决方案。
答案 0 :(得分:1)
即使您能够将ProductDTO投射到产品型号,EF也不会自动跟踪这些对象。
一种可能的解决方案可能是首先选择产品,然后迭代它们以分配所需的属性。
答案 1 :(得分:0)
在您的第一个(失败的)查询中,我相信选择可以替换为:
select new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = ct
};
可能会有效。
否则,你无法施放&lt;&gt;从一种对象类型到另一种对象类型,除非它们具有基本/派生关系。否则,您需要转换它们:
在产品DTO中,添加:
替换:
return query.Cast<Product>();
使用:
return query.Select(p=> new Product
{
ID = p.ID,
Name = p.Name,
Description = p.Description,
CategoryTrans = p.CategoryTrans
};
更新:
好吧,让我们尝试不同的东西。 删除查询中的选择,只需使用p
对象:
public static IQueryable<Product> ActiveProductsPerUser(BaseContext db,
string userid, string culture)
{
var query = from p in db.Products
join ct in db.CategoryTrans
on p.CategoryID equals ct.category_id
join l in db.ISO_Languages
on ct.language_id equals l.ID
where l.code.Substring(0, 2) == culture;
return query;
}
将CategoryTrans
属性保留为null,但它将引导您完成此操作以及查询的其他操作。当你走到尽头,并且实际上正在处理结果时,请拔出p.Category.CategoryTrans.Where(b => b.language_id.Equals(l.ID)).FirstOrDefault()
以获得CategoryTrans
答案 2 :(得分:0)
我找不到
的答案实体或复杂类型&#39; xyz.DAL.Product&#39;不能在LINQ to Entities查询中构造。
错误。我最终通过添加
解决了这个问题CATEGORY_LAUNCHER
到产品型号类,负责显示本地化的类别名称,并将过滤移动到ViewModel,设置两个嵌套的foreach循环,返回一个新的完全本地化产品列表:
[NotMapped]
public virtual string LocalizedCategoryName { get; set; }
不知道它是最佳还是唯一的方式,但按预期工作。我现在可以使用简单查询并将返回的Product的IQueryable传递给排序和分页异步方法或其他任何方法。每当我完成时,结果将被分配给ViewModel.LocalizedProductList,其中getter负责最终过滤。感谢wonderbell的建议,一个可能的解决方案是首先选择产品,然后迭代它们以分配所需的属性。这就是为什么对他/她的帖子进行投票,即使它不能被视为问题的完整(甚至部分)解决方案。