不确定标题是否有意义,但这就是我正在做的事情。我正在使用AutoMapper将我的实体框架实体映射到我的DTO对象,反之亦然。当我尝试将DTO数据映射到EF实体时出现问题。 EntityKey没有属性映射的属性。为了解决这个问题,我做了以下几点:
Mapper.CreateMap<VideoDTO, Video>()
.ForMember(dest => dest.EntityKey, opt =>
opt.ResolveUsing<VideoEntityKeyResolver>());
VideoEntityKeyResolver类如下所示:
public class VideoEntityKeyResolver : ValueResolver<VideoDTO, EntityKey>
{
protected override EntityKey ResolveCore(VideoDTO source)
{
EntityKey key = new EntityKey("EntityFrameworkTestingEntities.Videos",
"VideoId", source.VideoId);
return key;
}
}
我想知道是否有一种更通用的方法来实现这一点,我可以拥有一个带有构造函数的类,该构造函数在构造函数中包含实体集名称,键属性名称和键值。
我已经考虑过将一个EntityKey属性添加到我的DTO对象中,听起来很像是跨越流,因为创建DTO对象的重点是在我的应用程序的其余部分严重依赖于我的数据层。
在完全不相关的注释上(如果需要,我可以创建一个新问题),在使用AutoMapper时,我到底需要在哪里定义映射?目前我在我的上下文对象(这是我的EF存储库对象)的构造函数中进行此操作,但我认为这相当昂贵而且不正确,但是,它可以工作。
答案 0 :(得分:8)
我还没有测试过这个,但以下情况应该有效:
public class EntityKeyResolver<T, TProperty> : ValueResolver<T, EntityKey> where T : class
{
private Expression<Func<T, TProperty>> _propertyExpression;
private string _qualifiedEntitySetName;
private string _keyName;
public EntityKeyResolver(string qualifiedEntitySetName, string keyName, Expression<Func<T, TProperty>> propertyExpression)
{
_qualifiedEntitySetName = qualifiedEntitySetName;
_keyName = keyName;
_propertyExpression = propertyExpression;
}
protected override EntityKey ResolveCore(T source)
{
return new EntityKey(_qualifiedEntitySetName, _keyName, ExpressionHelper.GetValue(_propertyExpression));
}
}
ExpressionHelper
是一个静态类,我用它来帮助评估各种情况下的表达式。 GetValue方法如下所示:
internal static TProperty GetValue<T, TProperty>(T obj, Expression<Func<T, TProperty>> expression) where T : class
{
if (obj == null)
{
return default(TProperty);
}
Func<T, TProperty> func = expression.Compile();
return func(obj);
}
然后你会改变你的代码如下(假设VideoId是一个Guid):
Mapper.CreateMap<VideoDTO, Video>()
.ForMember(dest => dest.EntityKey, opt => opt.ResolveUsing(new EntityKeyResolver<VideoDTO, Guid>("EntityFrameworkTestingEntities.Videos", "VideoId", v => v.VideoId)));
可能比你想要的更冗长。通用解析器的替代方法是使用MapFrom映射实体密钥(它们大致相同的冗长):
Mapper.CreateMap<VideoDTO, Video>()
.ForMember(dest => dest.EntityKey, opt => opt.MapFrom(src => new EntityKey("EntityFrameworkTestingEntities.Videos", "VideoId", src.VideoId)));
关于你的另一个问题,我养成了创建一个初始化我的map的静态类的习惯,并设置了一个布尔值,看是否已经创建了映射,因为你只需要为每个AppDomain调用一次。然后,在我的存储库的构造函数中,我只需调用MapInitializer.EnsureMaps();