使用AutoMapper将LINQ查询结果映射到ViewModel对象

3
首先,一些背景信息...我正在使用Telerik MVC Grid来显示数据。该网格期望将IEnumerable传递到他们的GridModel类中,我认为这会处理分页、排序、过滤等操作。
为了避免通过ajax以JSON格式传递此数据时出现循环引用,我需要将我的EF linq查询结果映射到视图模型对象...AutoMapper是我首选的方法,但是我想到的唯一涉及AutoMapper的解决方案会严重影响性能。
我有一个存储库将我的视图模型类型的IEnumerable返回给我的由网格调用的操作方法。
public IEnumerable<ResultViewModel> Search()
    {
        var person = _context.Persons;

         //this works and is the best performance wise but could be made simpler with automapper
        var result = person.Select(x => new ResultViewModel
                            {
                                FirstName = x.firstName,
                                LastName = x.lastName,
                                ///etc...
                            });

        //THIS IS SLOW but works
        //var result = Mapper.Map<IEnumerable<Person>, IEnumerable<ResultViewModel>>(person);

        //this does not work and errors at runtime
        //var result = person.Select(x => Mapper.Map<Person, ResultViewModel>(x));

        return result;

    }

有没有什么办法可以在使用AutoMapper简化操作的同时保持我的性能?我猜想,使用AutoMapper的慢速版本是由于person集合被枚举...然后稍后由Telerik Grid解析造成的。


你在 person.Select(x => Mapper.Map<Person, ResultViewModel>(x)) 中遇到了什么错误? - smartcaveman
@smartcaveman 错误为:LINQ to Entities 不识别该方法......,且该方法无法转换为存储表达式。 - stephen776
这意味着 IQueryable 没有被评估。 jfar 的答案应该有效。 - smartcaveman
1个回答

1

听起来你遇到了一个 Select ( N + 1 ) 的问题,循环中的每个项目都在加载相关属性,因此会发出另一个 select 查询。

使用 automapper 不应该有任何性能问题。

在进行自动映射之前,尝试在 person 上调用 ToList()(难道不应该是 people 吗?)并打破 IQueryable 链。


尝试使用ToList(),但问题仍然存在...使用快速方法,我的请求大约需要50毫秒...而使用automappper方法,则需要700-850毫秒。 - stephen776
关闭您上下文中的延迟加载功能,然后重试。 - John Farrell
关闭懒加载虽然减少了响应时间的几百毫秒,但也阻止了我从相关类返回属性。 - stephen776
1
@stephen776 - 那么你确实有一个选择 N + 1 的问题。使用 .Include 函数来预先加载相关实体。 - John Farrell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接