【问题标题】:Partial loading of Entity Framework entities and passing them to presentation layer实体框架实体的部分加载并将它们传递给表示层
【发布时间】:2011-12-21 12:24:15
【问题描述】:

如果我想在检索 EF 实体的数据时只选择几列并将它们转换为 Entity 类型,我不能这样做,因为它会引发本文中提到的错误 The entity cannot be constructed in a LINQ to Entities query。我不想选择所有列,因为我只需要其中的几个。我可以使用匿名类型,但是如果我使用存储库模式并且想要将所有数据访问代码封装在存储库对象中并将强类型对象集合传递给控制器​​(不是匿名对象集合),我该如何实现呢?是为 EF 实体的每个属性子集定义 DTO 对象的唯一选择吗?我知道部分加载的实体存在丢失数据的风险,但如果我准备承担风险并希望完全控制数据更新,这不可能吗?

例如,我希望“ProductRepository”方法签名是这样的

public IEnumerable<Product> GetProducts(int categoryID) //selection of subset of data

并且我想将此产品集合从控制器传递到视图(在 ASP.NET MVC 项目中),并且在视图中我希望拥有强类型模型(带有智能感知)对象。这可能吗?如果没有,由于这个限制,我可能不得不重新考虑在我的项目中使用 EF。我使用的是 EF 4.1 版本。

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework entity-framework-4.1 repository-pattern


    【解决方案1】:

    是的,这种情况下的选项是您要选择的每个属性子集的特殊对象。您可以调用对象 DTO,因为它只是投影的结果。这是正确的方法,因为如果您的 UI 不需要实体类型的其他属性,则只传递专门的 ViewModel 是正确的。

    另一个更复杂(更糟糕)的选项是在 Linq-to-entities 查询中选择匿名类型,调用 ToList,然后构建真实的实体类型。不允许部分实体选择,也不允许投影到映射的实体类型。这就是为什么您必须使用这种繁琐的方法的原因。示例:

    // Select anonymous projection
    var query = from x in context.Entities
                where ...
                select new { ... };
    
    // Repopulate entity type
    var reultSet = query.ToList().Select(x => new Entity { ... });
    

    【讨论】:

    • 感谢您的回复。它可以工作,但是首先填充匿名对象集合然后从中填充实体集合效率低下。我宁愿为属性的每个子集都有一个 DTO,尽管它对我来说是一个代码膨胀。从表中选择所有列也是低效的(可能会导致大型表出现性能问题),如果我只对其中一些感兴趣,那么从表中选择所有列是没有意义的。
    • ViewModels 通常在 UI 层中定义,如果我需要将其转换为存储库层中的 ViewModel,那么我将不得不在另一个项目中定义它们,因为存储库层无法引用 UI层。
    • ViewModels 通常在 UI 中定义,但来自存储库层的 DTO 可以是您的 ViewModel。选择匿名类型然后将其转换回实体类型的解决方案没有任何您应该烦恼的低效率。它只是更复杂。
    【解决方案2】:

    是的,使用视图模型而不是实体完全可以实现您想要的。这是示例控制器代码:

    var productEntities = productRepos.GetProducts(6);
    var productViewModels = Automapper.Mapper
        .Map<IEnumerable<ProductViewModel>>(productEntities);
    return View(productViewModels);
    

    您的视图模型将仅具有视图所需的属性。查看自动映射器。

    【讨论】:

    • 但在这段代码中,我必须从 Product 表中选择所有列,然后创建一个名为“ProductViewModel”的新类,其中包含列的子集。我想要的是将部分加载的实体从存储库传递到控制器,然后直接从那里传递到视图。
    • 为什么?您是否担心从数据库传递的数据过多的网络性能?
    • 是的,对于小表来说没关系,但是对于大表来说,从表中选择所有内容可能会导致性能问题,为什么在只需要少数列的情况下选择所有内容?为每个子集定义 DTO 需要更多工作,但目前似乎没有其他选择,除了另一个答案中建议的解决方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    相关资源
    最近更新 更多