【问题标题】:AutoMapper - strongly typed data setAutoMapper - 强类型数据集
【发布时间】:2013-11-21 14:23:08
【问题描述】:

我有这样定义的映射:

Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>();

MyRowDto 是 TMyRow 的 1:1 副本,但所有属性都是自动属性。

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")]
public string PositionFolder{
    get {
        try {
            return ((string)(this[this.tableTMyDataSet.PositionFolderColumn]));
        }
        catch (global::System.InvalidCastException e) {
            throw new global::System.Data.StrongTypingException("The value for column \'PositionFolder\' in table \'TMyDataSet\' is DBNull.", e);
        }
    }
    set {
        this[this.tableTMyDataSet.PositionFolderColumn] = value;
    }
}

当我打电话时:

DsMyDataSet.TMyRow row = ....;
AutoMapper.Mapper.Map<MyRowDto>(row);

我收到 StrongTypingException 异常,因为该列中的值为空。该属性可以为空,但强类型数据集不支持可以为空的属性,您必须调用 IsNullable instea。 如何在 AutoMapper 中解决此问题,以便进行映射(忽略错误并保留空值)?

【问题讨论】:

    标签: c# automapper strongly-typed-dataset


    【解决方案1】:

    我认为解决这个问题最简单的方法是使用IMemberConfigurationExpression&lt;DsMyDataSet.TMyRow&gt;.Condition() 方法并使用try-catch 块来检查访问源值是否会抛出StrongTypingException

    这是您的代码最终的样子:

    Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>()
          .ForMember( target => target.PositionFolder,
            options => options.Condition(source => { 
                 try { return source.PositionFolder == source.PositionFolder; }
                 catch(StrongTypingException) { return false; } 
          });
    

    如果这种情况很常见,那么您还有其他一些选择可以避免为每个成员编写所有这些代码。

    一种方法是使用扩展方法:

    Mapper
    .CreateMap<Row,RowDto>()
    .ForMember( target => target.PositionFolder, options => options.IfSafeAgainst<Row,StrongTypingException>(source => source.PositionFolder) )
    

    当解决方案中出现以下情况时:

     public static class AutoMapperSafeMemberAccessExtension
     {
         public static void IfSafeAgainst<T,TException>(this IMemberConfigurationExpression<T> options, Func<T,object> get)
             where TException : Exception
         {
             return options.Condition(source => {
                 try { var value = get(source); return true; }
                 catch(TException) { return false; }
             });
         }
     } 
    

    AutoMapper 也有一些内置的扩展点,也可以在这里使用。我突然想到的几种可能性是:

    1. 定义一个自定义的IValueResolver 实现。您可以在解决方案中使用类似的实现:NullReferenceExceptionSwallowingResolver。您可能可以复制该代码,然后只更改指定您正在处理的异常类型的部分。 Documentation for configuration is on the AutoMapper wiki,但配置代码看起来像:

      Mapper.CreateMap<Row,RowDto>()
        .ForMember( target => target.PositionFolder, 
              options => options.ResolveUsing<ExceptionSwallowingValueResolver<StrongTypingException>>());
      

    【讨论】:

      【解决方案2】:

      使用此映射:

      Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>()
          .ForMember(s => s.PositionFolder, o => o.MapFrom(d => !d.IsPositionFolderNull() ? d.PositionFolder: null));
      

      【讨论】:

        【解决方案3】:

        在较新版本的 Automapper 中,如果 DataRow 属性为 DBNull,通常可以通过使用 IMemberConfigurationExpression&lt;TSource, TDestination, TMember&gt;.PreCondition() 来阻止它们被映射:

              var config = new MapperConfiguration(
                cfg =>
                  {
                    cfg.CreateMap<DsMyDataSet.TMyRow, MyRowDto>();
        
                    cfg.ForAllMaps((typeMap, map) =>
                      {
                        map.ForAllMembers(opt =>
                          {
                            opt.PreCondition((src, context) =>
                              {
                                var row = src as DataRow;
                                if (row != null)
                                {
                                  return !row.IsNull(opt.DestinationMember.Name);
                                }
        
                                return true;
                              });
                          });
                      });
                  });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-22
          • 2017-03-23
          • 2023-03-10
          • 2013-02-16
          • 2011-01-22
          • 1970-01-01
          • 2010-09-19
          • 2016-07-20
          相关资源
          最近更新 更多