cho*_*bo2 26 c# nhibernate performance automapper asp.net-mvc-3
嗨我有一些自动映射器的主要问题,它很慢.我不知道如何加快速度.
我正在使用nhibernate,流利的nhibernate和asp.net mvc 3.0
[Serializable()]
    public class Test
    {
        public virtual int Id { get; private set; }
        public virtual string Name { get;  set; }
        public virtual string Description { get; set; }
        public virtual DateTimeDate { get; set; }
        public virtual IList<Reminder> Reminders { get; set; }
        public virtual IList<Reminder2> Reminders2 { get; set; }
        public virtual Test2 Test2 { get; set; }
        public Test()
        {
            Reminders = new List<Reminders>();
            Reminders2 = new List<Reminders2>();
        }
    }
所以你可以看到我得到了一些属性,在我的数据库中有一些其他类我在它们之间有引用.
然后我这样做
var a = // get all items (returns a collection of Test2)
var List<MyViewModel> collection = new List<MyViewModel>();
     foreach (Test2 t in a)
            {
                MyViewModel vm = Mapper.Map<Test2, MyViewModel>(t);
                vm.SetDateFormat(t.DateTimeDate, DateFilters.All.ToString());
                collection.Add(vm);
            }
//查看模型
    public class MyViewModel
        {
            public int Id  { get; private set; }
            public string Name { get; set; }
            public string Description { get; set; }
            public DateTime DateTimeDate { get; set; }
            public string FormatedDueDate { get; set; }
            public string Test2Prefix { get; set; }
            public string Test2BackgroundColor { get; set; }
            public string SelectedDateFilter { get; set; }
            public bool DescState { get; set; }
            public bool AlertState { get; set; }
            /// <summary>
            /// Constructor
            /// </summary>
            public MyViewModel()
            {
                // Default values
                SelectedDateFilter = "All";
                DescState = false;
                AlertState = false;
            }
            /// <summary>
            /// Sets the date formatter string used
            /// </summary>
            /// <param name="dateFormat"></param>
            public void SetDateFormat(DateTime dueDate, string dateFilter)
            {
                // simple if statement to format date.
            }
        }
//映射
  Mapper.CreateMap<Test2,MyViewModel>().ForMember(dest => dest.DescState, opt =>
 opt.ResolveUsing<DescStateResolver>())
                 .ForMember(dest => dest.AlertState, opt =>
 opt.ResolveUsing<AlertStateResolver>());
解析器
public class AlertStateResolver : ValueResolver<Task, bool>
    {
        protected override bool ResolveCore(Task source)
        {
            if (source.Reminders.Count > 0 || source.Reminders2.Count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }   
  public class DescStateResolver : ValueResolver<Task,bool>
    {
        protected override bool ResolveCore(Task source)
        {
            if (String.IsNullOrEmpty(source.Description))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
忽略奇怪的名字和任何错别字我的真实对象工作得很好并且有意义.
所以我用秒表做了这个
Stopwatch a = new Stopwatch()
    foreach (Test2 t in a)
                {
                    a.Start()                     
                    MyViewModel vm = Mapper.Map<Test2, MyViewModel>(t);
                    a.Stop()
                    vm.SetDateFormat(t.DateTimeDate, DateFilters.All.ToString());
                    collection.Add(vm);
                }
var b = a.Elapsed; // comes back with 32 seconds.
我需要非常好地优化它.
Dar*_*rov 28
代替:
var a = // get all items (returns a collection of Test2)
List<MyViewModel> collection = new List<MyViewModel>();
foreach (Test2 t in a)
{
    MyViewModel vm = Mapper.Map<Test2, MyViewModel>(t);
    vm.SetDateFormat(t.DateTimeDate, DateFilters.All.ToString());
    collection.Add(vm);
}
尝试:
var a = // get all items (returns a collection of Test2)
List<MyViewModel> collection = Mapper.Map<IEnumerable<Test2>, IEnumerable<MyViewModel>>(a);
除了SetDateFormat您可以在映射定义中进行的调用之外,它等同于第一个.它也可能更快.
如果您在Test2 => MyViewModelAutoMapper 之间定义了映射,则自动提供一个映射,IEnumerable<Test2> => IEnumerable<MyViewModel>以便您不需要循环.
你也在你的问题中提到过NHibernate.确保源对象及其集合在将数据传递到映射层之前急切地从数据库加载,或者您不能责怪AutoMapper因为速度缓慢,因为当它尝试映射源对象的其中一个集合时它会访问数据库,因为NHibernate没有获取此集合.
Aar*_*nLS 28
要寻找的另一件事是映射抛出异常的代码.AutoMapper将以静默方式捕获这些内容,但以这种方式捕获异常会影响性能.
因此,如果SomethingThatMightBeNull通常为null,则由于NullreferenceExceptions,此映射将执行得很差:
.ForMember(dest => dest.Blah, c.MapFrom(src=>src.SomethingThatMightBeNull.SomeProperty))
我发现这样的更改将超过映射所需的一半时间:
.ForMember(dest => dest.Blah, c.MapFrom(src=> (src.SomethingThatMightBeNull == null
    ? null : src.SomethingThatMightBeNull.SomeProperty)))
更新:C#6语法
.ForMember(dest => dest.Blah, c.MapFrom(src => (src.SomethingThatMightBeNull?.SomeProperty)))
a.b*_*ema 12
添加此功能后,能够改善启动时间
 .ForAllMembers(options => options.Condition(prop => prop.SourceValue != null));
在每个结尾
.CreateMap<..,..>()
| 归档时间: | 
 | 
| 查看次数: | 22531 次 | 
| 最近记录: |