Linq Projection不包括原始实体的所有数据

时间:2012-11-30 03:39:41

标签: linq linq-to-entities automapper

我遇到过LINQ问题,希望你能帮我弄清楚。

以下是发生的事情。

  1. 我从存储库中获得IQueryable<LicenseEntity>个实体。
  2. 我查看这些实体中的字段,看到它们包含有效数据。 LicenseEntity中有一个相关实体Customer的字段。它也包含有效数据,因为我使用LicenseEntity加载它。
  3. 我使用.Select将每个LicenseEntity投影到LicenseViewModel。
  4. 对于每个LicenseEntity,LicenseEntity都会传递到AutoMapper.Mapper.Map并加载到LicenceViewModel实体中。
  5. 在处理完所有实体之后,当我查看调试器中的LicenseViewModel列表时,它会报告一个空引用异常,并且没有要查看的项目。
  6. 要确定AutoMapper是否导致我的问题,我将其替换为MapMe()。当我停在MapMe中的return语句并查看s参数(原始实体)时,我发现其中的数据没问题,但客户字段现在为空。我认为Select做了一些我不知道的事情。
  7. 如何Select在进行投影时保留原始实体中的所有信息?我们的解决方案无法实现列表,因为它可能非常非常大。我已将下面的测试代码包含在内,非常感谢您的帮助。

    // Get the IQueryable<LicenseEntity> list of licenses from the repository.
    var list = LicenseRepository.List();
    
    // Convert the IQueryable<LicenseEntity> to an IQueryable<LicenseViewModel>
    var vmlist = list.Select(x => MapMe(x, new LicenseViewModel()));
    //var vmlist = list.Select(x => AutoMapper.Mapper.Map(x, new LicenseViewModel()));
    
    // This function was used to see the LicenseEntity that was passing into Map().
    // I discovered that the entity has all the correct data except for a related
    // entity field, which was present in the original LicenseEntity before         
    public LicenseViewModel MapMe(LicenseEntity s, LicenseViewModel d)
    {
        return d;
    }
    

    以下代码正常工作,但它实现了实体,我们无法做到。

    List<LicenseViewModel> vms = new List<LicenseViewModel>();
    foreach (var item in list)
    {
        var vm = AutoMapper.Mapper.Map(item, new LicenseViewModel());
        vms.Add(vm);
    }
    

3 个答案:

答案 0 :(得分:1)

您已对此LINQ-to-Entities进行了标记,但未在文中提及基础技术。但问题很可能是由于关联对象的延迟加载造成的。

这是一个适用于我曾经使用过的大多数ORM的设计选择。加载对象时,默认情况下不会加载连接的对象。如果它们在默认情况下被加载,很明显你会快速破坏所有内容

  • 加载许可证时,会自动加载相关客户
  • 加载客户时,会加载所有相关对象 - 公司,地址,所有其他许可等
  • 对于每个对象,每个相关对象都被加载......

答案是您需要指定要加载的相关对象。在实体框架中,您执行此操作using the Include method

因为您正在使用存储库抽象,您可能会发现它比它需要的更难,但是在不知道更多的情况下我无法给出任何建议。这种类型的功能 - 非常基本的东西 - 总是存储库和“工作单元”模式的难度。

答案 1 :(得分:0)

我认为您的映射应该更像:

var vms = Mapper.Map<List<LicenseEntity>, List<LicenseViewModel>>(list);

(即 - 您不需要foreach循环)。

但不幸的是,我非常怀疑这会解决你的问题,因为我怀疑这也会实现你的实体。

答案 2 :(得分:0)

我找到了将域实体投影到视图模型的解决方案。如果您遇到与我相同的问题,请查看以下链接:

http://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/ http://www.devtrends.co.uk/blog/stop-using-automapper-in-your-data-access-code

顺便说一句,在一个我的域实体中,我有一个带有一些“计算”属性的部分类...其值是从数据库记录中的其他字段生成的属性。这些不能在域实体中,因为它们会干扰上述解决方案。我把它们移到我的ViewModel类,这是他们真正需要的地方,一切都很好。

希望这些信息有助于......

麦克