我使用ADO.NET C#POCO实体生成器Visual Studio外接程序为我的实体生成POCO类。
当我尝试在Linq to Entities查询中使用该类时,如下所示:
var q = from w in entities.Widgets
select new Widget
{
Id = w.Id,
WidgetName = w.WidgetName,
WidgetDescription = w.WidgetDescription
};
return q.ToList();
我得到以下异常:
“无法在LINQ to Entities查询中构造实体或复杂类型MyNamespace.Widget”。
唯一的解决方法是使用匿名类型,然后使用另一个LINQ查询:
var q = from w in entities.Widgets
select new
{
Id = w.Id,
WidgetName = w.WidgetName,
WidgetDescription = w.WidgetDescription
};
var r = from e in q.AsEnumerable()
select new Widget
{
Id = e.Id,
WidgetName = e.WidgetName,
WidgetDescription = e.WidgetDescription
};
return r.ToList();
这有效,但非常多余。我理解为什么我会得到例外,但是有更优雅的方法吗?
POCO类由ADO.NET C#POCO实体生成器生成的事实似乎与此问题无关;我尝试使用自己的POCO类并看到了相同的异常。
非常感谢。
编辑: 添加了使用ADO.NET C#POCO实体生成器Visual Studio加载项的演练链接 - http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx
答案 0 :(得分:4)
我猜MyNamespace.Widget
是自定义类 - 而不是EDM的一部分?
如果是这样,您无法将LINQ-Entities查询投影到自定义类型中。如果您使用POCO,无关紧要。
你有一个正确的想法投射到匿名类型。
在服务器上具体化查询后,您可以在客户端上调整查询形式:
var widgets = entities
.Widgets
.ToList() // materialize query
.Select(x => new Widget
{
Id = w.Id,
WidgetName = w.WidgetName,
WidgetDescription = w.WidgetDescription
}
).ToList();
哪个比你的解决方案好一点。
但这引出了一个问题 - 为什么你不首先在EDM上返回“Widget”类型?
POCO的重点在于你可以将持久性逻辑分成简单的类。所以我不确定为什么你从简单类型(POCO)投射到另一个(看似相同)的简单类型。您是否将POCO映射到DTO用于N层传输?
答案 1 :(得分:2)
这个page表明这是因为您在Entity Framework范围之外创建了一个Entity对象,这显然是不允许的。他们基本上使用与您相同的解决方法,通过在初始选择后双重选择匿名类型的结果。
如果这是我,我可能只需选择w
并完成它,或创建一个新的特殊视图类型类来适应Widget的特殊化,从而避免所有这些。希望有一个比这更好的答案:)