实体框架 + AutoMapper(实体到DTO和DTO到实体)

发布于 2024-07-20 02:52:09 字数 920 浏览 8 评论 0原文

我在使用 EF 和 AutoMapper 时遇到一些问题。 =/

例如:

我有 2 个相关实体(客户和订单) 它们是 DTO 类:


class CustomerDTO
{
   public string CustomerID {get;set;}
   public string CustomerName {get;set;}
   public IList< OrderDTO > Orders {get;set;}
}

订单DTO类 { 公共字符串订单ID {获取;设置;} 公共字符串 OrderDetails {get;set;} 公共 CustomerDTO 客户 {get;set;} }

//当将Entity映射到DTO时,代码可以工作 客户 cust = getCustomer(id); Mapper.CreateMap< 客户,CustomerDTO >(); Mapper.CreateMap< 订单,OrderDTO >(); CustomerDTO custDTO = Mapper.Map(cust);

//但是当我尝试从 DTO 映射回实体时,它失败并出现 AutoMapperMappingException。 映射器.Reset(); Mapper.CreateMap< CustomerDTO ,客户 >(); Mapper.CreateMap< OrderDTO ,订单 >(); 客户 customerModel = Mapper.Map< 客户DTO,客户>(custDTO); // 这里抛出异常

难道我做错了什么?

提前致谢 !

I've got some problems using EF with AutoMapper. =/

for example :

I've got 2 related entities ( Customers and Orders )
and they're DTO classes :


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

Am I doing something wrong?

Thanks in Advance !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

顾北清歌寒 2024-07-27 02:52:10

我遇到的问题与 EntityCollection 引用的更新有关。 从 DTO 映射到实体时,AutoMapper 会创建关系的新实例,这并不能让 EF 满意。

解决我问题的方法是将 AutoMapper 配置为使用 EntityCollection 属性的目标值。 在您的情况下:

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

这样 AM 将不会创建新的 EntityCollection 实例,并将使用原始 Customer 实体附带的实例。

我仍在寻找一种自动化的方法,但现在它解决了我的问题。

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.

望她远 2024-07-27 02:52:10

尝试映射到现有对象:

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

并保留 Ignore() 的位置。

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

Try mapping to an existing object:

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

And keep the Ignore()'s in place.

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

国产ˉ祖宗 2024-07-27 02:52:10

您的问题是因为 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

Your problem is because Automapper loses the EntityKey associated with the record. As the EntityFramework does not by default handle POCO's (Plain Old CLR Object)

Jay Zimmerman has a good example here of how to handle this from is. gd /4NIcj
Also from Jaroslaw Kowalski (part of the EF team I believe ) has this example for using POCO's within EF, which may translate well to use with Automapper (I've not yet had a chance to try it) : http://blogs.msdn.com/jkowalski/archive/2008/09/09/persistence-ignorance-poco-adapter-for-entity-framework-v1.aspx

听风念你 2024-07-27 02:52:10

我不确定你的问题是什么,但是 - 当我想使用 LINQToEntities (切换到 NHibernate)时,
我成功地使用了自动映射器。

看一下代码:

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);
    }
}

它非常神秘,总是重新创建映射,但它有效。 我希望它能有所帮助。 :)

I'm not sure what your problem is, but - when i wanted to use LINQToEntities (switched to NHibernate),
i managed to use automapper with success.

Take a look at code:

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);
    }
}

It's quite cryptic, always recreates mappings, but it worked. I hope it helps somehow. :)

温暖的光 2024-07-27 02:52:10

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

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

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

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

创建映射:

Mapper.CreateMap<Customer, CustomerDto>();

并将查询项目到 dto:

var customerDto = 
   session.Query<Customer>().Where(customer => customer.Id == id)
   .Project().To<CustomerDto>()
   .Single();

Now, with new version of AutoMapper, the recommended way is using Queryable-Extensions:

When using an ORM such as NHibernate or Entity Framework with
AutoMapper's standard Mapper.Map functions, you may notice that the
ORM will query all the fields of all the objects within a graph when
AutoMapper is attempting to map the results to a destination type.

If your ORM exposes IQueryables, you can use AutoMapper's
QueryableExtensions helper methods to address this key pain.

The .ProjectTo() will tell AutoMapper's mapping engine
to emit a select clause to the IQueryable that will inform entity
framework that it only needs to query the Name column of the Item
table, same as if you manually projected your IQueryable to an
OrderLineDTO with a Select clause.

Create a mapping:

Mapper.CreateMap<Customer, CustomerDto>();

And project query to dto:

var customerDto = 
   session.Query<Customer>().Where(customer => customer.Id == id)
   .Project().To<CustomerDto>()
   .Single();
云巢 2024-07-27 02:52:10

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

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

AutoMapper is very expressive when it comes to mapping error. read the exception message carefully.

another important thing is to remember to call Mapper.AssertConfigurationIsValid(); after creating the mappings. it gives an error if the mapping is wrong, thus preventing an exception later in the application runtime.

爱*していゐ 2024-07-27 02:52:10

您应该忽略某些实体属性的映射,如下所示:

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 抛出的异常中的消息,您应该看到无法映射的实体属性并忽略它们,如上所述。

You should ignore mapping of some entity properties like so:

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());

If you examine the message from the exception thrown by Automapper, you should see the entity properties that cannot be mapped and ignore them as above.

余生共白头 2024-07-27 02:52:10

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

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

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

还要注意映射问题,例如此处

这些技巧对我有用。

As you can read here you need to do the following

You can update entities with AutoMapper. Here's how: pass both the DTO and the entity object to AutoMapper's Map method. That's what this code does:

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

Also beware of mapping issues like the one described here

These tips worked for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文