【发布时间】:2015-09-28 18:39:11
【问题描述】:
在我的数据中,我有两个可以有地址的实体。在数据库中,这些列在每个表中都是重复的。我可能会在将来使这些正常化,但目前不想解决它。但是,在我的视图模型中,我确实将联系信息分解为一个单独的类,以便重复使用。
我正在尝试找出一种优雅的方式来映射这种情况下的属性。从数据库映射到视图模型很容易,但我正在努力处理反向视图模型到数据库模型。
以下是数据实体类(稍微简化):
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 和 IncludeBase。
我还考虑让 OrganizationEditModel 直接从 ContactInfoEditModel 继承,但我不确定这是否会弄乱我的 EditorTemplates(这仍然是一种解决方法,而不是正确解决方案)。
【问题讨论】:
标签: c# automapper