2012-09-19 55 views
2

我需要将EF中的一些POCO实体投影到它们的缩减视图模型表示中以传递给序列化程序。这种情况下的实体是装运和申请单,并且具有0..1的关系。如果我不传递视图模型,那么它会在尝试序列化Requisition和Shipment之间的循环引用时引发堆栈溢出异常。将嵌套实体嵌入到嵌套视图模型中

return db.ShipmentRequisitions 
       .Include(c => c.Shipment) 
       .Select(r => new ViewModels.Requisition 
       { 
        ID = r.ID, 
        ... 
        Shipment = r.Shipment != null ? new ViewModels.Shipment 
        { 
         ID = r.Shipment.ID, 
         ... 
        } : null 
       }).AsQueryable(); 

如果货件为空,则在尝试访问r.Shipment.ID时会出现异常。我像上面添加了一个空检查,现在得到以下异常。

无法创建类型'Api.ViewModels.Shipment'的常量值。 在此上下文中仅支持基本类型(如Int32,String和Guid) 。

这令我奇怪的,因为它是相当愉快创建嵌套ViewModels.Shipment作为选择的一部分,之前我加空校验,所以它必须有一些与此有关。

我可以在调用堆栈中看到一些EF,所以我在一个快速测试项目中尝试了一下,只用直接的对象用纯LINQ来尝试它。

var user = users.Select(u => new ViewModel.User 
       { 
        Id = u.Id, 
        Profile = u.Profile != null ? new ViewModel.Profile 
        { 
         Id = u.Profile.Id 
        } : null 
       }).ToList(); 

令我惊讶的工作。我无法弄清楚这在第一个代码示例中不起作用。

UPDATE

我发现,如果作为一个选择的一部分,我做这样的事情:

.Select(r => new ViewModels.Requisition 
        { 
         ID = r.ID, 
         ShipmentDescription = r.Shipment.Description 
        }) 

这是有效的扁平化所需的出货性质成一个单一的DTO。在设置Description属性时,如果Shipment在任何记录上为空,我希望得到一个NullReferenceExcetion。然而它并没有发生。 LINQ似乎抑制了这个异常,并且ShipmentDescription通过了null。它可以节省我对每个嵌套属性进行内联检查。不幸的是,当创建一个嵌套的对象时,这似乎并没有扩展到相同的东西。

+0

同样的问题在这里:http://stackoverflow.com/questions/10904375/can-i-project-an-optional-reference-of-an-entity-into-an-optional-reference-of-t你最后如果使用例如'ID = r.Shipment.ID'当'左侧ID'的例子就是BTW失败*在一个数据库中的记录不为空的*和'Shipment'是'NULL'。 – Slauma

回答

0

的问题是这一行:

.SingleOrDefault(r => r.ID == id);

EF试图表达r.ID == id转换为SQL,而不是管理。

的解决方案是简单地改变行: .ToEnumerable().SingleOrDefault(r => r.ID == id);

这工作,因为只有IQueryable的转换为SQL,不IEnumerable的。

+0

感谢您的回答。 SingleOrDefault不是必需的。我试图做同样的选择上都返回单个记录的方法,并返回一个IQueryable准备呼叫的人。在这两种情况下,它都有相同的问题。我已更新我的问题以反映这一点。 –

1

您可以在ViewModels.Requisition纳入ViewModels.Shipment对象,而空校验如果在Shipment类的所有属性都为空的。虽然这有点痛苦,因为现在Shipment对象仅在没有装运的情况下使用空值创建。

你也可以把它围:选择具有在他们Requisitions收藏Shipment模型。值得一试,如果它不会让你的应用程序的其他部分变得太糟糕。