Entity Framework 4 Proxy Pocos Automapper: mapping problem with inheritance and abstract base class on collections

.net automapper collections entity-framework poco

Question

The mapping of a business object to a DTO when I have inheritance off of an abstract base class inside a collection utilizing the fantastic technology AutoMapper is giving me trouble.

My items are as follows:

abstract class Payment
class CashPayment : Payment
class CreditCardPayment : Payment

I also have an invoice object with a group of payments organized as follows:

    public class Invoice
    {
       ... properties...

       public ICollection<Payment> Payments { get; set; }
    }

Each of these things also has a matching DTO version available.

What is the definition of the DtoInvoice object?

[DataContract]
public class DtoInvoice
{
   ...properties...

   [DataMember]
   public List<DtoPayment> Payments { get; set; }
}

My Mapper definitions look like this:

Mapper.CreateMap<Invoice, DtoInvoice>();

Mapper.CreateMap<Payment, DtoPayment>()
  .Include<CashPayment, DtoCashPayment>()
  .Include<CreditCardPayment, DtoCreditCardPayment>();

Mapper.CreateMap<CashPayment, DtoCashPayment>();
Mapper.CreateMap<CreditCardPayment, DtoCreditCardPayment>();

This is how the mapping code is written:

var invoice = repo.GetInvoice(invoiceId);

var dtoInvoice = Mapper.Map<Invoice, DtoInvoice>(invoice);

Thus, for instance, if my invoice object has a group of particular payments (for instance, one cash payment and one credit card payment), and the mapper attempts to map these, I get an error stating the abstract class Payment cannot be formed. The code runs if I remove the abstract keyword from the Payment object, however I only get a collection of Payment instances rather than their individual objects (Cash & Credit Card payments).

Consequently, the query is: How can I get AutoMapper to map the particular payment types rather than the base class?


Update

I believe I've found an issue after doing additional research, but I'm not sure how to use AutoMapper to fix it. I believe that EF is more to blame for this than AutoMapper. :-)

Entity Framework 4 Proxy POCOs with lazy loading are used in my code.

As a result, if I attempt to map an object supplied by EF that is a proxy POCO, I get the following strange-looking type:

System.Data.Entity.DynamicProxies.CashPayment_86783D165755C316A2F58A4343EEC4842907C5539AF24F0E64AEF498B15105C2

So, according to my idea, when AutoMapper attempts to map CashPayment to DtoCashPayment and the payment that was handed in is of the proxy type, AutoMapper perceives this as a "non match" and maps the generic Payment type instead. AutoMapper, however, fails with a "System.InvalidOperationException: Instances of abstract classes cannot be constructed." error since Payment is an abstract class.

I want to know whether there is a method for me to map EF POCO proxy objects to Dtos using AutoMapper.

1
39
8/15/2010 8:35:00 PM

Accepted Answer

This response is "a little" late since I just encountered the same problem with EF4 POCO proxies.

Using a specialized converter that callsMapper.DynamicMap<TDestination>(object source) instead than using the runtime type conversion,.Include<TOtherSource, TOtherDestinatio>() .

I can use it just well.

In your situation, you would define the converter as follows:

class PaymentConverter : ITypeConverter<Payment, DtoPayment> {
    public DtoPayment Convert( ResolutionContext context ) {
        return Mapper.DynamicMap<DtoPayment>( context.SourceValue );
    }
}

After that:

Mapper.CreateMap<Payment, DtoPayment>().ConvertUsing<PaymentConverter>();
Mapper.CreateMap<CashPayment, DtoCashPayment>();
Mapper.CreateMap<CreditCardPayment, DtoCreditCardPayment>();
15
12/23/2010 11:26:19 AM

Popular Answer

The same StackOverflow issues appeared when I used Olivier's example as well. Due to the fact that I was not utilizing a base class from the entity model code generation, I also attempted subkamran's technique, however it was unsuccessful. Automapper continues to crash. I just configured the Context to not construct Proxies when I create a Context object till I discover a better solution.

model.Configuration.ProxyCreationEnabled = false; 
model.Configuration.LazyLoadingEnabled = true; 

I would also want to see a solution to the issue, maybe using something included with Automapper.

UPDATE: The Automapper Pre-release fixes this problem and enables the mapping to cover a DynamicProxy without further settings.

This is compatible with release 2.2.1.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow