将嵌套实体项目嵌入到嵌套视图模型中

时间:2012-09-19 13:19:32

标签: c# linq entity-framework

我需要将一些POCO实体从EF投影到他们的剪切视图模型表示中,以便传递给序列化器。这种情况下的实体是装运和申请,并且具有0..1关系。如果我没有传递视图模型,那么在尝试序列化请购单和发货之间的循环引用时,它会抛出一个堆栈溢出异常。

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();

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

  

无法创建“Api.ViewModels.Shipment”类型的常量值。   仅支持原始类型(例如Int32,String和Guid')   在这种情况下。

这让我感到很奇怪,因为我很高兴在添加空检查之前创建嵌套的ViewModels.Shipment作为select的一部分,所以它必须与此有关。

我可以在调用堆栈中看到一些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();

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

更新

我发现如果作为选择的一部分,我会做类似的事情:

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

这有效地将所需的货件属性展平为单个DTO。在设置Description属性时,如果Shipment在任何记录上为空,我希望得到NullReferenceExcetion。然而,它不会发生。 LINQ似乎抑制了异常,ShipmentDescription也是空的。它节省了我对每个嵌套属性的内容进行内联检查。不幸的是,在创建一个我没有展平的嵌套对象时,这似乎并没有扩展到同样的东西。

2 个答案:

答案 0 :(得分:1)

如果ViewModels.Shipment类中的所有属性都可以为空,则可以在ViewModels.Requisition中合并Shipment个对象而不进行空检查。但这有点痛苦,因为现在Shipment对象仅在没有货物的情况下使用空值创建。

您也可以将其转过来:选择其中包含Shipment个集合的Requisitions个模型。值得一试,如果它不会使你的应用程序的其余部分搞得太多。

答案 1 :(得分:0)

问题在于这一行:

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

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

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

这是有效的,因为只有IQueryable被转换为SQL,而不是IEnumerable。