【问题标题】:Entity Framework + AutoMapper ( Entity to DTO and DTO to Entity )实体框架 + AutoMapper(实体到 DTO 和 DTO 到实体)
【发布时间】:2009-05-21 09:03:53
【问题描述】:

我在使用带有 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

我做错了吗?

提前致谢!

【问题讨论】:

  • 您的“客户”和“订单”实体是什么样的?如果没有看到它们的结构,很难说出发生了什么......
  • 我也不能......在 entitycollection 和 dto 列表之​​间映射时遇到问题。
  • 正如@geva30 所提到的,您应该在创建地图后致电Mapper.AssertConfigurationIsValid() 以确定您在运行时可能遇到的任何问题
  • 你也可以试试 EntitiesToDTOs,一个实体框架 DTO 生成器,用作 Visual Studio 的插件:entitiestodtos.codeplex.com

标签: c# entity-framework automapper dto


【解决方案1】:

我遇到的问题与 EntityCollection 引用的更新有关。 AutoMapper 在从 DTO 映射到实体时创建关系的新实例,这不符合 EF。

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

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

这样,AM 不会创建新的 EntityCollection 实例,而是使用原始客户实体附带的那个。

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

【讨论】:

    【解决方案2】:

    尝试映射到现有对象:

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

    并保持 Ignore() 就位。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我不确定您的问题是什么,但是 - 当我想使用 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);
            }
        }
        

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

        【讨论】:

        • 您能否提供一个使用您描述的代码连接 AUtoMapper 的示例?
        • @Oppositional public class CustomerRepository{ Customer lameMethod(){LinqGeneratedCustomer generatedCustomer; ...tralala ...返回地图(生成的客户};}
        【解决方案5】:

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

        当使用诸如 NHibernate 或实体框架之类的 ORM 时 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();
        

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:

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

            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 引发的异常的消息,您应该会看到无法映射的实体属性并像上面一样忽略它们。

            【讨论】:

              【解决方案8】:

              您可以阅读here,您需要执行以下操作

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

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

              还要注意像here 中描述的映射问题

              这些技巧对我有用。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-06-16
                • 2011-08-20
                • 2013-10-19
                • 2011-08-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-12-18
                相关资源
                最近更新 更多