AutoMapper - 从两个源映射表达式导致异常

时间:2018-05-02 10:17:58

标签: c# asp.net asp.net-web-api expression automapper

我使用的是Asp.Net Core 2.0,Automapper 6.2.2

在我的项目中,我希望AutoMapper允许从两个源映射到一个目标(相反)。请考虑以下型号:

class UserA {
 public CustomerId {get;set;}
 public CustomerName {get;set;}
}

class UserB {
 public CustomerId {get;set;}
 public CustomerEmail {get;set;}
}

class UserViewModel{
 public Id {get;set;}
 public CustomerName {get;set;}
 public CustomerEmail {get;set;}   
}

我的AutoMapper配置文件配置如下:

CreateMap<UserA , UserViewModel>()
              .ForMember(dest => dest.Id , opt => opt.MapFrom(src => src.CustomerID))
              .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.CustomerName)).ReverseMap()
             .ForAllOtherMembers(x => x.Ignore());

CreateMap<UserB , UserViewModel>()
              .ForMember(dest => dest.Id , opt => opt.MapFrom(src => src.CustomerID))
              .ForMember(dest => dest.CustomerEmail , opt => opt.MapFrom(src => src.CustomerEmail )).ReverseMap()
             .ForAllOtherMembers(x => x.Ignore());

我有一个公开UserViewModel的Rest API,应该允许根据Id,CustomerName或CustomerEmail过滤结果。 API使用者不应该知道CustomerName和CustomerEmail属于哪个实体。

我已经创建了一种服务方法:

public override async Task<IEnumerable<UserViewModel>> GetAsync(Expression<Func<UserViewModel, bool>> filter = null, Expression<Func<IQueryable<UserViewModel>, IOrderedQueryable<UserViewModel>>> orderBy = null, string includeProperties = null, int? skip = null, int? take = null)

现在我想映射两个参数

Expression<Func<UserViewModel, bool>> filter
Expression<Func<IQueryable<UserViewModel>, IOrderedQueryable<UserViewModel>>> orderBy

Expression<Func<UserA, bool>> filterA
Expression<Func<IQueryable<UserA>, IOrderedQueryable<UserA>>> orderByA

Expression<Func<UserB, bool>> filterB
Expression<Func<IQueryable<UserB>, IOrderedQueryable<UserB>>> orderByB

但是当我使用UserEmail应用过滤器并希望映射到UserA时,映射会给我一个例外。我希望AutoMapper忽略配置Ignored的表达式的所有部分。

var filterA= Mapper.Map<Expression<Func<UserA, bool>>>(filter);

给出例外

ArgumentNullException: Value cannot be null.
Parameter name: memberInfo

AutoMapper.Internal.ReflectionHelper.GetMemberType(MemberInfo memberInfo)
AutoMapperMappingException: Error mapping types.

Mapping types:
Expression1`1 -> Expression`1
System.Linq.Expressions.Expression1`1[[System.Func`2[[Cluster.Users.ViewModel.UserDetailViewModel, Cluster.User, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] -> System.Linq.Expressions.Expression`1[[System.Func`2[[Cluster.Model.SimsModel.UserDetail, Cluster.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]

lambda_method(Closure , Expression1<Func<UserDetailViewModel, bool>> , Expression<Func<UserDetail, bool>> , ResolutionContext )

最后一个问题是UserA和UserB存储在两个独立的数据库中,因此它们是使用两个不同的db上下文从数据库中提取的。

修改

我还尝试过Automapper投影,它似乎正确地获取数据,但它分别获取所有相关集合(在我的问题中,我提供了一个简化的模型来更好地解释问题,但真正的实体有依赖的一对多关系)。 另一个问题是它也破坏了体系结构,因为我必须从存储库中获取GetQueryable()并在服务中构建查询,而不是直接将所有参数传递给存储库。

var usersA = _readOnlyRepository.GetQueryable<UserA>().ProjectTo<UserViewModel>().Where(filter).ToList();
var usersB = _readOnlyRepository.GetQueryable<UserB>().ProjectTo<UserViewModel>().Where(filter).ToList();

0 个答案:

没有答案