我在使用EF和AutoMapper时遇到了一些问题。 = /
例如:
我有2个相关实体(客户和订单) 他们是DTO课程:
class CustomerDTO { public string CustomerID {get;set;} public string CustomerName {get;set;} public IList< OrderDTO > Orders {get;set;} }
class OrderDTO { public string OrderID {get;set;} public string OrderDetails {get;set;} public CustomerDTO Customers {get;set;} }
//when mapping Entity to DTO the code works Customers cust = getCustomer(id); Mapper.CreateMap< Customers, CustomerDTO >(); Mapper.CreateMap< Orders, OrderDTO >(); CustomerDTO custDTO = Mapper.Map(cust);
//but when i try to map back from DTO to Entity it fails with AutoMapperMappingException. Mapper.Reset(); Mapper.CreateMap< CustomerDTO , Customers >(); Mapper.CreateMap< OrderDTO , Orders >(); Customers customerModel = Mapper.Map< CustomerDTO ,Customers >(custDTO); // exception is thrown here
我做错了吗?
提前致谢!
答案 0 :(得分:18)
我遇到的问题与EntityCollection引用的更新有关。当从DTO映射到实体时,AutoMapper会创建关系的新实例,而不会取悦EF。
解决了我的问题是配置AutoMapper以使用我的EntityCollection属性的目标值。在你的情况下:
Mapper.CreateMap< CustomerDTO , Customers >().ForMember(c => c.Orders, o => o.UseDestinationValue());
这样AM就不会创建新的EntityCollection实例,并且将使用原始Customer实体附带的实例。
我仍然在努力实现自动化,但是现在它解决了我的问题。
答案 1 :(得分:5)
您的问题是因为Automapper丢失了与记录关联的EntityKey。由于EntityFramework默认情况下不处理POCO(普通旧CLR对象)
Jay Zimmerman在这里有一个很好的例子,说明如何处理这个问题。 gd / 4NIcj 同样来自Jaroslaw Kowalski(EF团队的一部分,我相信)有一个在EF中使用POCO的例子,可以很好地转换为与Automapper一起使用(我还没有机会尝试):http://blogs.msdn.com/jkowalski/archive/2008/09/09/persistence-ignorance-poco-adapter-for-entity-framework-v1.aspx < / p>
答案 2 :(得分:4)
我不确定你的问题是什么,但是 - 当我想使用LINQToEntities(切换到NHibernate)时, 我成功地使用了automapper。
看看代码:
public class SimpleMapper<TFrom, TTo>
{
public static TTo Map(TFrom fromModel)
{
Mapper.CreateMap<TFrom, TTo>();
return Mapper.Map<TFrom, TTo>(fromModel);
}
public static IList<TTo> MapList(IList<TFrom> fromModel)
{
Mapper.CreateMap<TFrom, TTo>();
return Mapper.Map<IList<TFrom>, IList<TTo>>(fromModel);
}
}
public class RepositoryBase<TModel, TLINQModel>
{
public IList<TModel> Map<TCustom>(IList<TCustom> model)
{
return SimpleMapper<TCustom, TModel>.MapList(model);
}
public TModel Map(TLINQModel model)
{
return SimpleMapper<TLINQModel, TModel>.Map(model);
}
public TLINQModel Map(TModel model)
{
return SimpleMapper<TModel, TLINQModel>.Map(model);
}
public IList<TModel> Map(IList<TLINQModel> model)
{
return SimpleMapper<TLINQModel, TModel>.MapList(model);
}
public IList<TLINQModel> Map(IList<TModel> model)
{
return SimpleMapper<TModel, TLINQModel>.MapList(model);
}
}
它非常神秘,总是重新创建映射,但它确实有效。我希望它有所帮助。 :)
答案 3 :(得分:4)
尝试映射到现有对象:
entity = Mapper.Map<MyDTO, NyEntity>(dto, entity);
并将Ignore()保持在原位。
http://groups.google.com/group/automapper-users/browse_thread/thread/24a90f22323a27bc?fwc=1&pli=1
答案 4 :(得分:3)
现在,使用新版本的AutoMapper,推荐的方法是使用Queryable-Extensions:
使用NHM或ORMP框架等ORM时 AutoMapper的标准Mapper.Map函数,你可能会注意到 ORM将在图表中查询所有对象的所有字段 AutoMapper正在尝试将结果映射到目标类型。
如果你的ORM暴露了IQueryables,你可以使用AutoMapper QueryableExtensions帮助方法来解决这个关键的痛苦。
.ProjectTo()将告诉AutoMapper的映射引擎 向IQueryable发出一个select子句,它将通知实体 它只需要查询Item的Name列的框架 表,就像手动将IQueryable手动投影到一样 带有Select子句的OrderLineDTO。
创建映射:
var customerDto =
session.Query<Customer>().Where(customer => customer.Id == id)
.Project().To<CustomerDto>()
.Single();
将项目查询到dto:
{{1}}
答案 5 :(得分:2)
AutoMapper在映射错误方面非常具有表现力。仔细阅读异常消息。
另一个重要的事情是要记住调用Mapper.AssertConfigurationIsValid();创建映射后。如果映射错误,则会出错,从而在应用程序运行时稍后阻止异常。
答案 6 :(得分:2)
您应该忽略某些实体属性的映射,如下所示:
Mapper.CreateMap<CustomerDto, Customer>()
.ForMember(dest => dest.EntityKey, opt => opt.Ignore())
.ForMember(dest => dest.Licenses, opt => opt.Ignore())
.ForMember(dest => dest.AccessCodes, opt => opt.Ignore());
如果检查来自Automapper抛出的异常的消息,您应该看到无法映射的实体属性,并忽略它们。
答案 7 :(得分:0)