在我的数据中,我有两个可以拥有地址的实体。在数据库中,这些列在每个表中都是重复的。我可能会在将来规范化,但不想在此刻解决它。但是,在我的视图模型中,我确实将联系信息分解为一个可以重复使用的单独类。
我正试图找出一种在这种情况下映射属性的优雅方法。从数据库到视图模型的映射很容易,但我正在努力使用反向视图模型到数据库模型。
以下是数据实体类(简化了一点):
public abstract class EntityWithContactInfo
{
[MaxLength(50)]
public string Street1 { get; set; }
[MaxLength(50)]
public string Street2 { get; set; }
[MaxLength(30)]
public string City { get; set; }
[MaxLength(30)]
public string State { get; set; }
[MaxLength(10)]
public string Zip { get; set; }
[MaxLength(10)]
public string Phone { get; set; }
[MaxLength(100)]
public string Email { get; set; }
}
public class Organization : EntityWithContactInfo
{
public int OrganizationId { get; set; }
[MaxLength(100), Required]
public string FullName { get; set; }
[MaxLength(100), Required]
public string DisplayName { get; set; }
public string Website { get; set; }
public string Information { get; set; }
}
public class Agent : EntityWithContactInfo
{
public int AgentId { get; set; }
[MaxLength(30), Required]
public string LastName { get; set; }
[MaxLength(20), Required]
public string FirstName { get; set; }
public string Comments { get; set; }
}
以下是我的观点模型(我还没有代理人 - 先在组织工作):
public class ContactInfoEditModel
{
[StringLength(50)]
[Display(Name = "Street Address 1")]
public string Street1 { get; set; }
[StringLength(50)]
[Display(Name = "Street Address 2")]
public string Street2 { get; set; }
[StringLength(30)]
public string City { get; set; }
[StringLength(30)]
public string State { get; set; }
[StringLength(10)]
public string Zip { get; set; }
[Display(Name = "Pimary Phone")]
public string Phone { get; set; }
[StringLength(100)]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
public abstract class EditModelBaseWithContactInfo
{
[Display(Name = "Contact Information")]
public ContactInfoEditModel ContactInfo { get; set; }
}
public class OrganizationEditModel : EditModelBaseWithContactInfo
{
[Display(Name = "Id")]
public int OrganizationId { get; set; }
[Required, StringLength(100)]
[Display(Name = "Full Name")]
public string FullName { get; set; }
[Required, StringLength(100)]
[Display(Name = "Display Name")]
public string DisplayName { get; set; }
[Url(ErrorMessage = "Please enter a valid URL (including the protocol: http:// or https://).")]
public string Website { get; set; }
[UIHint("HtmlEditor")]
[AllowHtml]
public string Information { get; set; }
}
我现在对映射的看法是这样的:
Mapper.CreateMap<EntityWithContactInfo, ContactInfoEditModel>();
Mapper.CreateMap<Organization, OrganizationEditModel>()
.MapEditModelBaseWithContactInfo();
Mapper.CreateMap<OrganizationEditModel, Organization>()
.MapEntityWithContactInfo();
private static IMappingExpression<TEntity, TModel> MapEditModelBaseWithContactInfo<TEntity, TModel>(this IMappingExpression<TEntity, TModel> mapping)
where TEntity : EntityWithContactInfo
where TModel : EditModelBaseWithContactInfo
{
return mapping.ForMember(m => m.ContactInfo, exp => exp.MapFrom(e => Mapper.Map<ContactInfoEditModel>(e)));
}
private static IMappingExpression<TModel, TEntity> MapEntityWithContactInfo<TModel, TEntity>(this IMappingExpression<TModel, TEntity> mapping)
where TModel : EditModelBaseWithContactInfo
where TEntity : EntityWithContactInfo
{
return mapping.MapEntityModifiable()
.ForMember(e => e.Street1, exp => exp.MapFrom(m => m.ContactInfo.Street1))
.ForMember(e => e.Street2, exp => exp.MapFrom(m => m.ContactInfo.Street2))
.ForMember(e => e.City, exp => exp.MapFrom(m => m.ContactInfo.City))
.ForMember(e => e.State, exp => exp.MapFrom(m => m.ContactInfo.State))
.ForMember(e => e.Zip, exp => exp.MapFrom(m => m.ContactInfo.Zip))
.ForMember(e => e.Email, exp => exp.MapFrom(m => m.ContactInfo.Email))
.ForMember(e => e.State, exp => exp.MapFrom(m => m.ContactInfo.State))
.ForMember(e => e.Phone, exp => exp.MapFrom(m => m.ContactInfo.Phone));
}
我在静态映射类中创建了最后两个扩展方法,这样当我添加代理映射时,我不必复制.ForMember调用。如您所见,从数据模型到视图模型的映射看起来很好。然而,第二种扩展方法是我在努力的地方。它工作正常,但它似乎不是正确方式。正如您所看到的,我已明确列出了Organization / ContactInfo上的所有属性,即使它们都具有相同的名称(AutoMapper通常会自行处理)
似乎应该有一种方法告诉AutoMapper将Source的ContactInfo属性上的所有属性直接映射到Destination。有谁知道你是怎么做到的?我玩过Include&lt;&gt;和IncludeBase&lt;&gt;。
我还考虑让OrganizationEditModel直接从ContactInfoEditModel继承,但我不确定这是否会弄乱我的EditorTemplates(这仍然是一种解决方法,而不是正确的解决方案)。
答案 0 :(得分:0)
查看ConvertUsing
。第二种扩展方法可能如下所示:
private static IMappingExpression<TModel, TEntity> MapEntityWithContactInfo<TModel, TEntity>(this IMappingExpression<TModel, TEntity> mapping)
where TModel : EditModelBaseWithContactInfo
where TEntity : EntityWithContactInfo
{
return mapping.MapEntityModifiable()
.ConvertUsing(x => Mapper.Map<TEntity>(x.ContactInfo));
}