Entity Framework + AutoMapper (Entity to DTO et DTO to Entity)

j'ai quelques problèmes avec L'utilisation de EF avec AutoMapper. = /

par exemple :

j'ai 2 entités liées ( clients et commandes ) et ce sont des cours de 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

je fais quelque chose de mal?

Merci d'Avance !

19
demandé sur Daniel Schilling 2009-05-21 13:03:53

8 réponses

le problème que j'avais était lié à des mises à jour des références EntityCollection. AutoMapper crée une nouvelle instance de la relation lors de la correspondance de la DTO à L'entité, et cela ne plaît pas à L'EF.

ce qui a résolu mon problème a été la configuration D'AutoMapper pour utiliser la valeur de destination pour mes propriétés EntityCollection. Dans ton cas:

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

de cette façon AM ne créera pas une nouvelle instance EntityCollection, et utilisera ce qui est venu avec le client original entité.

je travaille toujours à trouver un moyen d'automatiser ça, mais pour l'instant ça résout mon problème.

17
répondu Pablo Montilla 2010-05-28 17:59:19

votre problème est que Automapper perd L'EntityKey associé à l'enregistrement. Comme L'Entitefram Framework ne gère pas par défaut POCO's (Plain Old CLR Object)

Jay Zimmerman a un bon exemple ici de la façon de gérer cela à partir des SI. gd / 4NIcj Aussi de Jaroslaw Kowalski (partie de L'équipe EF je crois ) a cet exemple pour l'utilisation de POCO au sein de EF, qui peut traduire bien à utiliser avec Automapper (Je n'ai pas encore eu la chance de l'essayer) : http://blogs.msdn.com/jkowalski/archive/2008/09/09/persistence-ignorance-poco-adapter-for-entity-framework-v1.aspx

5
répondu user203510 2009-11-05 14:54:34

Je ne suis pas sûr de ce qu'est votre problème, mais-quand je voulais utiliser LINQToEntities (commuté en NHibernate),

j'ai réussi à utiliser automapper avec succès.

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

c'est assez cryptique, il recrée toujours des mappages, mais ça a marché. J'espère qu'elle vous aide en quelque sorte. :)

4
répondu Arnis Lapsa 2009-05-21 09:21:22

Essayez d'associer à un objet existant:

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

Et de garder l'Ignore()'s en place.

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

4
répondu ishakkulekci 2011-12-29 15:39:34

maintenant, avec la nouvelle version D'AutoMapper, la façon recommandée est d'utiliser Queryable-Extensions:

Lorsqu'on utilise un ORM tel que NHibernate ou Entity Framework avec AutoMapper standard du Mappeur.Fonctions de la carte, vous pouvez noter que le ORM va requête tous les champs de tous les objets dans un graphique quand AutoMapper tente de faire correspondre les résultats à un type de destination.

si votre ORM expose des Iquerables, vous pouvez utiliser AutoMapper de l' Les méthodes d'aide de QueryableExtensions pour répondre à cette douleur clé.

le .ProjectTo () avertira le moteur de cartographie D'AutoMapper pour émettre une clause select à L'IQueryable qui informera l'entité cadre qu'il ne doit interroger la colonne Nom de l'Élément table, comme si vous aviez projeté manuellement votre IQueryable OrderLineDTO avec une clause Select.

Créer un mapping:

Mapper.CreateMap<Customer, CustomerDto>();

et requête de projet à dto:

var customerDto = 
   session.Query<Customer>().Where(customer => customer.Id == id)
   .Project().To<CustomerDto>()
   .Single();
3
répondu Dvor_nik 2016-02-03 11:53:30

AutoMapper est très expressif en ce qui concerne les erreurs de mappage. lisez attentivement le message d'exception.

une autre chose importante est de ne pas oublier d'appeler Mapper.AssertConfigurationIsValid (); après avoir créé les mappings. il donne une erreur si la cartographie est faux, empêchant ainsi une exception plus tard dans l'exécution de l'application.

2
répondu geva30 2009-10-18 17:09:50

Vous devriez ignorer la cartographie de certaines propriétés d'entity comme 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());

si vous examinez le message de l'exception lancée par Automapper, vous devriez voir les propriétés de l'entité qui ne peuvent pas être mappées et les ignorer comme ci-dessus.

2
répondu codrin 2011-10-07 15:29:42

Comme vous pouvez le lire ici vous devez faire ce qui suit

Vous pouvez mettre à jour des entities avec AutoMapper. Voici comment: passez la DTO et l'objet entity à la méthode Map D'AutoMapper. C'est ce que ce code:

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

attention aussi aux problèmes de mappage comme celui décrit ici

ces conseils ont fonctionné pour moi.

0
répondu Dmytro I. 2014-01-18 20:17:59