AutoMapper - 强类型数据集

5

我的映射定义如下:

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

MyRowDto是TMyRow的一对一拷贝,但所有属性都是自动属性。

[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。 在AutoMapper中如何解决此问题,使映射继续进行(忽略错误并保留null值)?

3个回答

2
请使用以下映射:
Mapper.CreateMap<DsMyDataSet.TMyRow, MyRowDto>()
    .ForMember(s => s.PositionFolder, o => o.MapFrom(d => !d.IsPositionFolderNull() ? d.PositionFolder: null));

2

我认为解决这个问题最简单的方法是使用IMemberConfigurationExpression<DsMyDataSet.TMyRow>.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. Define a custom IValueResolver implementation. There is already a similar implementation in the solution that you could use: the NullReferenceExceptionSwallowingResolver. You could probably copy that code and then just change the part that specifies what kind of exception you're working with. Documentation for configuration is on the AutoMapper wiki, but the configuration code would look something like:

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

0
在较新版本的Automapper中,可以通过使用IMemberConfigurationExpression<TSource,TDestination,TMember>.PreCondition()来通常防止映射DataRow属性,如果它们是DBNull
      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;
                      });
                  });
              });
          });

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