22

我在使用带有 AutoMapper 的 EF 时遇到了一些问题。=/

例如 :

我有 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

难道我做错了什么?

提前致谢 !

4

8 回答 8

20

The problem I had was related to updates to EntityCollection references. AutoMapper creates a new instance of the relation when mapping from the DTO to the Entity, and that doesn't please the EF.

What solved my problem was configuring AutoMapper to use the destination value for my EntityCollection properties. In your case:

Mapper.CreateMap< CustomerDTO , Customers >().ForMember(c => c.Orders, o => o.UseDestinationValue());

That way AM will not create a new EntityCollection instance, and will use that wich came with the original Customer entity.

I'm still working for a way to automate this, but for now it solves my problem.

于 2010-05-28T17:59:19.400 回答
6

尝试映射到现有对象:

entity = Mapper.Map<MyDTO, NyEntity>(dto, entity); 

并保持 Ignore() 就位。

http://groups.google.com/group/automapper-users/browse_thread/thread/24a90f22323a27bc?fwc=1&pli=1

于 2011-12-29T15:32:55.590 回答
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

于 2009-11-05T14:54:34.167 回答
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);
    }
}

它非常神秘,总是重新创建映射,但它确实有效。我希望它以某种方式有所帮助。:)

于 2009-05-21T09:21:22.567 回答
3

现在,使用新版本的 AutoMapper,推荐的方法是使用Queryable-Extensions

当使用诸如 NHibernate 或实体框架之类的 ORM 和 AutoMapper 的标准 Mapper.Map 函数时,您可能会注意到,当 AutoMapper 尝试将结果映射到目标类型时,ORM 将查询图中所有对象的所有字段。

如果您的 ORM 公开 IQueryables,您可以使用 AutoMapper 的 QueryableExtensions 辅助方法来解决这个关键问题。

.ProjectTo() 将告诉 AutoMapper 的映射引擎向 IQueryable 发出一个选择子句,该子句将通知实体框架它只需要查询 Item 表的 Name 列,就像您手动将 IQueryable 投影到 OrderLineDTO 一样选择子句。

创建映射:

Mapper.CreateMap<Customer, CustomerDto>();

并将项目查询到 dto:

var customerDto = 
   session.Query<Customer>().Where(customer => customer.Id == id)
   .Project().To<CustomerDto>()
   .Single();
于 2016-02-03T11:47:23.210 回答
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 引发的异常的消息,您应该会看到无法映射的实体属性并如上所述忽略它们。

于 2011-10-07T15:29:42.503 回答
2

AutoMapper 在映射错误方面非常有表现力。仔细阅读异常消息。

另一个重要的事情是记住调用 Mapper.AssertConfigurationIsValid(); 创建映射后。如果映射错误,它会给出错误,从而防止稍后在应用程序运行时出现异常。

于 2009-10-18T17:09:50.327 回答
0

如您在此处阅读的,您需要执行以下操作

您可以使用 AutoMapper 更新实体。方法如下:将 DTO 和实体对象都传递给 AutoMapper 的 Map 方法。这就是这段代码的作用:

custExisting = Mapper.Map(Of CustomerDTO,  Customer)(custDTO, custExisting)

还要注意此处描述的映射问题

这些技巧对我有用。

于 2014-01-18T20:17:59.167 回答