【问题标题】:Linq Projection is not including all data from the original entityLinq Projection 不包括来自原始实体的所有数据
【发布时间】:2012-12-01 15:09:27
【问题描述】:

我遇到了一个 LINQ 问题,希望您能帮我解决。

这就是正在发生的事情。

  1. 我从存储库中获得了 IQueryable<LicenseEntity> 的实体。
  2. 我查看了这些实体中的字段,发现它们包含有效数据。 LicenseEntity 中有一个相关实体Customer 的字段。它也包含有效数据,因为我使用 LicenseEntity 加载了它。
  3. 我使用.Select 将每个 LicenseEntity 投影到 LicenseViewModel。
  4. 对于每个 LicenseEntity,一个 LicenseEntity 被传递到 AutoMapper.Mapper.Map 并被加载到一个 LicenseViewModel 实体中。
  5. 在处理完所有实体后,当我在调试器中查看 LicenseViewModels 列表时,它会报告空引用异常并且没有要查看的项目。
  6. 为了确定 AutoMapper 是否是导致我的问题的原因,我将其替换为 MapMe()。当我停在 MapMe 中的 return 语句,查看 s 参数,这是原始实体时,我发现其中的数据是可以的,只是现在客户字段为空。我假设Select 做了一些我不知道的事情。

如何使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);
}

【问题讨论】:

    标签: linq linq-to-entities automapper


    【解决方案1】:

    您已标记此LINQ-to-Entities,但文中未提及底层技术。但问题很可能是关联对象的延迟加载引起的。

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

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

    答案是您需要指定要加载哪些相关对象。在实体框架中,您可以这样做using the Include method

    因为您使用的是存储库抽象,您可能会发现这比实际需要的要困难,但在不了解更多信息的情况下,我无法提供任何建议。这种类型的功能——非常基本的东西——对于存储库和“工作单元”模式来说总是一个难题。

    【讨论】:

    • 嗨,柯克,感谢您的回复。我已经明确告诉查询加载相关项目,并且当我使用调试器在投影之前检查“列表”时它存在。这就是为什么我对为什么执行投影时相关项目为空感到困惑的原因。 ??? :)
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 你也可以用'var vms = Mapper.Map(list)'进行映射;这里有“列表”的任何具体原因?
    • 我不知道这个选项,但很有意义。将尝试使用我的应用程序。谢谢。
    • 嗨 Swani & Mightymuke,实际上,“list”的赋值有很多参数,所以我删除了它们以使代码更易于阅读。 Swani,您的代码不会导致列表实现吗?如果是这样,这是一种解决方法,但我的要求是不实现。 :( 我当然想知道为什么投影不能正常工作......
    【解决方案3】:

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

    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 类,这是真正需要它们的地方,一切都很好。

    希望这些信息对您有所帮助...

    迈克

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-25
      • 2013-06-21
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多