Linq Projection不包括原始实体的所有数据 [英] Linq Projection is not including all data from the original entity

查看:62
本文介绍了Linq Projection不包括原始实体的所有数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了LINQ问题,希望您能帮助我解决这个问题.

这是正在发生的事情.

  1. 我从存储库中获得实体的IQueryable<LicenseEntity>.
  2. 我查看了这些实体中的字段,发现它们包含有效数据. LicenseEntity中有一个相关实体Customer的字段.它也包含有效数据,因为我已将其与LicenseEntity一起加载.
  3. 我使用.Select将每个LicenseEntity投影到一个LicenseViewModel.
  4. 对于每个LicenseEntity,LicenseEntity都传递到AutoMapper.Mapper.Map中,并加载到LicenceViewModel实体中.
  5. 在处理完所有实体之后,当我在调试器中查看LicenseViewModels列表时,它报告了一个空引用异常,并且没有要查看的项目.
  6. 要确定AutoMapper是否导致我的问题,我将其替换为MapMe().当我在MapMe中的return语句处停止并查看s参数(它是原始实体)时,我发现其中的数据还可以,除了customer字段现在为空.我认为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-to-Entities,但本文中没有提及底层技术.但是问题很可能是由关联对象的延迟加载引起的.

这是一种设计选择,适用于我使用过的大多数ORM.加载对象时,默认情况下不加载连接的对象.如果默认情况下加载了这些文件,则很明显,您会很快破坏所有内容

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

答案是,您需要指定要加载哪些相关对象.在Entity Framework中,您可以使用Include方法. /p>

由于您使用的是存储库抽象,因此您可能会发现这比需要的困难得多,但是在不了解更多信息的情况下,我无法提供任何建议.这种类型的功能-非常基本的东西-始终是存储库和工作单元"模式的难点.

I have encountered a LINQ issue and hope that you can help me to figure it out.

Here is what is happening.

  1. I get an IQueryable<LicenseEntity> of entities from the repository.
  2. I look at the fields in these entities and see that they contain valid data. There is a field for a related entity Customer in the LicenseEntity. It contains valid data, too, because I loaded it with the LicenseEntity.
  3. I use .Select to project each LicenseEntity to a LicenseViewModel.
  4. For each LicenseEntity, a LicenseEntity is passed into AutoMapper.Mapper.Map and is loaded into a LicenceViewModel entity.
  5. After all of the entities have been processed, when I look at the list of LicenseViewModels in the debugger, it reports a null reference exception and there are no items to view.
  6. To determine whether AutoMapper what causing my problem, I replaced it with a MapMe(). When I stopped at the return statement in MapMe and looked at the s parameter, which is the original entity, I found that the data in it is okay except that the customer field is now null. I assume that Select has done something that I don't know about.

How I can make Select retain all of the information in the original entity when it is doing its projection? Our solution cannot materialize the list because it may be very, very large. I've included my test code below and would really appreciate your help.

// 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;
}

The following code works properly however it materializes the entities, which we cannot do.

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

解决方案

You've tagged this LINQ-to-Entities but there's no mention of the underlying technology in the text. But it's very likely that the problem is caused by lazy loading of associated objects.

This is a design choice that applies to most ORMs that I've worked with. When you load an object, connected objects are not loaded by default. If they were loaded by default it's quite clear you'd quickly break everything

  • when you load a Licence, the related Customer is automatically loaded
  • when the Customer is loaded all related objects are loaded - Company, Address, all other Licences, etc
  • for each of those objects, every related object is loaded...

The answer is that you need to specify which related objects to load. In the Entity Framework you do this using the Include method.

Because you are using a repository abstraction you might find this more difficult than it needs to be, but without knowing more I can't give any advice. This type of functionality - pretty basic stuff - is always a difficulty with repositories and 'unit-of-work' patterns.

这篇关于Linq Projection不包括原始实体的所有数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆