AutoMapper - 强类型数据集
Posted
技术标签:
【中文标题】AutoMapper - 强类型数据集【英文标题】:AutoMapper - strongly typed data set 【发布时间】: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 中解决此问题,以便进行映射(忽略错误并保留空值)?
【问题讨论】:
【参考方案1】:我认为解决这个问题最简单的方法是使用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 也有一些内置的扩展点,也可以在这里使用。我突然想到的几种可能性是:
定义一个自定义的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<TSource, TDestination, TMember>.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;
);
);
);
);
【讨论】:
以上是关于AutoMapper - 强类型数据集的主要内容,如果未能解决你的问题,请参考以下文章