【问题标题】:Automapper performance自动映射器性能
【发布时间】:2016-12-01 20:30:35
【问题描述】:

我正在使用 Automapper 将我的业务模型映射到 ViewModel。

可以,但是速度很慢。

我有一个包含 6893 个对象和 23 个属性的集合(测试环境,生产应该有更多)。

使用循环需要00:02:32.8118534 来映射所有内容。

var objects = // get all items (returns a collection of MyObj)
List<MyViewModel> collection = new List<MyViewModel>();
foreach (MyObj obj in objects)
{
     MyViewModel vm = Mapper.Map<MyObj, MyViewModel>(obj);
     collection.Add(vm);
}

我试着像这样改进它:

var objects = // get all items (returns a collection of MyObj)
IEnumerable<MyViewModel> collection = mapper.Map<IEnumerable<MyObj>, IEnumerable<MyViewModel>>(objects);

00:02:25.4527961 绘制了所有内容。

所以它并没有太大帮助。

我的对象的所有属性都不能是null

这就是我配置映射器的方式:

var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<MyObj, MyViewModel>();
            cfg.CreateMap<MyObjOtherObj, MyViewModelOtherObj>();
        });
mapper = config.CreateMapper();

我的对象:

public partial class MyObj
{
    public MyObj()
    {
        this.MyObjOtherObj= new HashSet<MyObjOtherObj>();
    }

    public long a{ get; set; }
    public short b{ get; set; }
    public string c{ get; set; }
    public string d{ get; set; }
    public string e{ get; set; }
    public string f{ get; set; }
    public string g{ get; set; }
    public string h{ get; set; }
    public string i{ get; set; }
    public string j{ get; set; }
    public string k{ get; set; }
    public string l{ get; set; }
    public string m{ get; set; }
    public bool n{ get; set; }
    public bool o{ get; set; }
    public bool p{ get; set; }
    public bool q{ get; set; }

    public virtual ICollection<MyObjOtherObj> MyObjOtherObj{ get; set; }
    public virtual Types Types { get; set; }
}

MyViewModel:

public class MyViewModel
{
    public long a{ get; set; }
    public short b{ get; set; }
    public string c{ get; set; }
    public string d{ get; set; }
    public string e{ get; set; }
    public string f{ get; set; }
    public string g{ get; set; }
    public string h{ get; set; }
    public string i{ get; set; }
    public string j{ get; set; }
    public string k{ get; set; }
    public string l{ get; set; }
    public string m{ get; set; }
    public bool n{ get; set; }
    public bool o{ get; set; }
    public bool p{ get; set; }
    public bool q{ get; set; }
    public string TypesDescription { get; set; }

    public List<MyViewModelOtherObj> MyObjOtherObj { get; set; }
}

MyObjOtherObj:

public partial class MyObjOtherObj
{
    public long id{ get; set; }
    public long MyObjId { get; set; }
    public short x{ get; set; }
    public string z{ get; set; }

    public virtual MyObj MyObj{ get; set; }
    public virtual SourceTypes SourceTypes { get; set; }
}

MyViewModelOtherObj:

public class MyViewModelOtherObj
{
    public long Id { get; set; }
    public long MyObjId { get; set; }
    public short x{ get; set; }
    public string z{ get; set; }
    public string SourceTypesDescription { get; set; }
}

编辑:

来源类型:

public partial class SourceTypes
{
    public SourceTypes()
    {
        this.MyObjOtherObj = new HashSet<MyObjOtherObj>();
    }

    public short SourceTypeId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<MyObjOtherObj> MyObjOtherObj { get; set; }
}

类型:

public partial class Types
{
    public Types()
    {
        this.MyObj = new HashSet<MyObj>();
    }

    public short TypeId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<MyObj> MyObj{ get; set; }
}

【问题讨论】:

  • 能否请您发布两个对象的代码?
  • 那么你的问题是什么?您是否尝试过寻找热点?其他对象是如何创建的?
  • 您是否检查过它们是完全加载的对象,即 ORM 不会因为延迟加载附加对象而减慢速度?
  • @RichLinnell 是的,对象已完全加载。
  • 你用的是什么版本?

标签: c# performance automapper


【解决方案1】:

AutoMapper 5.0 版本的性能有了显着提升。在我们的基准测试中,使用您在此处显示的非常相似的类型,我们可以在一秒多一点的时间内映射一百万个项目。在即将到来的 5.1 版本中,这比手工映射慢了大约 3 倍,这主要是由于手工映射不会进行空值检查。

我会升级。

【讨论】:

  • 我使用的是最新版本(5.0.2)
  • 那么我真的很难过,我只是在我们的基准测试中运行了您的确切对象结构,并在 1.97 秒内映射了 1M 项。这是我的基准:gist.github.com/jbogard/faff8ad3f0a179618a9033781d8f4152
  • 我应该在 5.1 alpha 版本中添加这个,我们为它添加了一点性能。
  • 我检查了你的要点,几乎是一样的。不确定有什么区别。问题可能出在 objetcs Types 和 SourceTypes 上的虚拟属性上吗?两者都是实体框架创建的对象。 Types 有一个虚拟属性,它是 MyObj 的集合。 SourceTypes 是一个虚拟属性,它是 MyObjOtherObj 的集合。不确定 AutoMapper 是如何工作的。但这可能是一个以某种方式干扰 AutoMapper 的循环引用吗?
  • 否...问题可能出在对象 MyObjOtherObj 上的虚拟属性上吗?它也是实体框架创建的对象,有一个虚拟属性MyObj。
【解决方案2】:

为了响应我们的 cmets,您需要 Eager 加载您的集合对象。请查看以下文章,这应该可以解决您的问题:

Loading Related Entities

【讨论】:

  • 谢谢你!我不知道那件事。我将其更改为List&lt;MyObj&gt; myObjs = dbContext.MyObj.Include("MyObjOtherObj").ToList();,现在整个请求需要 13 秒(17803 个对象)。这并不完美,但可以接受。
猜你喜欢
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多