让Automapper忽略EF中的非标量和导航属性

时间:2012-09-30 03:31:27

标签: c# entity-framework automapper

需要使用automapper将域类型的属性从上下文映射回现有实体(基本上只是更新已更改的字段)。我需要它来忽略导航属性并只映射标量属性。

如果我说ForMember(o => o.MyNavProperty,opt => opt.Ignore),我可以让它工作但是我宁愿为我的所有映射都使用通用方法来告诉它只能映射标量而非导航属性。

尝试遵循Mauricio的解决方案:

ASP.net MVC - Should I use AutoMapper from ViewModel to Entity Framework entities?

但我无法成功忽略导航属性。

这是我的更新版本:

      private static void CreateMapForEF<TDto, TEntity>()
      {
         Mapper.CreateMap<TDto, TEntity>()
    .ForAllMembers(o => o.Condition(ctx =>
                                       {

                                          var members = ctx.Parent.SourceType.GetMember(ctx.MemberName); // get the MemberInfo that we are mapping

                                          if (!members.Any())
                                             return false;

                                          if (members.First().GetCustomAttributes(
                                                typeof (EdmRelationshipNavigationPropertyAttribute), false).Any())
                                             return false;

                                          return members.First().GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false).Any(); // determine if the Member has the EdmScalar attribute set

                                       }));
      }

2 个答案:

答案 0 :(得分:5)

我最近正在研究它 您可以使用以下解决方案:

定义导航属性的属性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class NavigationPropertyAttribute : Attribute
{
} 

在具有上述属性的View-Models中标记所有导航属性。

public class TagModel
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    public string Description { get; set; }

    [Display(Name = "Image")]
    public string ImagePath { get; set; }

    [NavigationProperty]
    public List<ContentModel> Contents { get; set; }
}

为AutoMapper编写扩展方法,以忽略具有NavigationProperty属性的所有属性。

public static IMappingExpression<TSource, TDestination> IgnoreNavigationProperties<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof(TSource);

    foreach (PropertyInfo property in sourceType.GetProperties())
    {
        var isNavProp = property.GetCustomAttributes(typeof(NavigationPropertyAttribute), false).Count() == 1;
        if (isNavProp)
                expression.ForMember(property.Name, opt => opt.Ignore());
    }
    return expression;
}

最后你可以按如下方式使用它:

Mapper.CreateMap<TagModel, Tag>()
        .ForMember(m => m.Id, opt => opt.Condition(m => m.Id > 0))
        .IgnoreNavigationProperties();

答案 1 :(得分:1)

我通过向实体添加接口并映射到接口或从接口映射来使用显式方法。因此,而不是排除我明确要包括什么。通过声明部分类来添加接口。

接口对我来说是免费的,因为我使用接口进行解耦,测试存根,模拟等。

也许只是我,但我不喜欢在AutoMapper配置中看到任何忽略。不能证明这一点,但这对我来说感觉不对。