我正在尝试实体框架代码第一个CTP4.假设我有:
public class Parent { public int Id { get; set; } public string Name { get; set; } } public class Child { public int Id { get; set; } public string Name { get; set; } public Parent Mother { get; set; } } public class TestContext : DbContext { public DbSet<Parent> Parents { get; set; } public DbSet<Child> Children { get; set; } } public class ChildEdit { public int Id { get; set; } public string Name { get; set; } public int MotherId { get; set; } } Mapper.CreateMap<Child,ChildEdit>();
映射到编辑模型不是问题.在我的屏幕上,我通过一些控件(下拉列表,自动完成等)选择母亲,并将母亲的身份发回:
[HttpPost] public ActionResult Edit(ChildEdit posted) { var repo = new TestContext(); var mapped = Mapper.Map<ChildEdit,Child>(posted); // <------- ??????? }
我应该如何解决最后的映射?我不想把Mother_Id放在Child对象中.现在我使用这个解决方案,但希望它可以在Automapper中解决.
Mapper.CreateMap<ChildEdit,Child>() .ForMember(i => i.Mother,opt => opt.Ignore()); var mapped = Mapper.Map<ChildEdit,Child>(posted); mapped.Mother = repo.Parents.Find(posted.MotherId);
编辑
这有效,但现在我必须为每个外键(BTW:上下文将注入最终解决方案):
Mapper.CreateMap<ChildEdit,Child>(); .ForMember(i => i.Mother,opt => opt.MapFrom(o => new TestContext().Parents.Find(o.MotherId) ) );
我真正喜欢的是:
Mapper.CreateMap<int,Parent>() .ForMember(i => i,opt => opt.MapFrom(o => new TestContext().Parents.Find(o)) ); Mapper.CreateMap<ChildEdit,Child>();
这是可能与Automapper?
解决方法
首先,我假设你有一个存储库接口,如IRepository< T>
之后创建以下类:
public class EntityConverter<T> : ITypeConverter<int,T> { private readonly IRepository<T> _repository; public EntityConverter(IRepository<T> repository) { _repository = repository; } public T Convert(ResolutionContext context) { return _repository.Find(System.Convert.ToInt32(context.SourceValue)); } }
基本上这个类将被用来执行int和domain实体之间的所有转换.它使用实体的“Id”将其从存储库加载. IRepository将使用IoC容器注入到转换器中,但更多和更晚.
我们来配置AutoMapper映射:
Mapper.CreateMap<int,Mother>().ConvertUsing<EntityConverter<Mother>>();
我建议创建这个“通用”映射,以便如果您在其他类中有其他引用“母亲”,则它们将自动映射而无需额外付费.
关于IRepository的依赖注入,如果您使用Castle Windsor,AutoMapper配置还应该具有:
IWindsorContainer container = CreateContainer(); Mapper.Initialize(map => map.ConstructServicesUsing(container.Resolve));