使用生成的POCO类在EF4中实现Linq to Entities

时间:2010-12-21 22:36:08

标签: entity-framework

我使用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

2 个答案:

答案 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的特殊化,从而避免所有这些。希望有一个比这更好的答案:)