Search code examples
c#entity-framework-6automapper

The cast to value type failed because the materialized value is null


I'm using AutoMapper to project my entities to models.

These are the models I'mm mapping to and from:

public partial class Material
{
    public System.Guid Id { get; set; }
    public string Description { get; set; }
    public string EAN { get; set; }

    public virtual InventoryLine InventoryLine { get; set; }
}

public partial class InventoryLine
{
    public System.Guid MaterialId { get; set; }
    public Nullable<decimal> Quantity { get; set; }
    public decimal Price { get; set; }
    public Nullable<System.DateTime> LastInspectionDate { get; set; }
    public int TransactionsSinceLastInspection { get; set; }

    public virtual Material Material { get; set; }
}

public class InventoryLineViewModel
{
    public string EAN { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public decimal? Quantity { get; set; }
    public DateTime? LastInspectionDate { get; set; }
}

I have this mapping:

CreateMap<Material, InventoryLineViewModel>().ForMember(d => d.Price, o => o.MapFrom(s => s.InventoryLine.Price)).ForMember(d => d.Quantity, o => o.MapFrom(s => s.InventoryLine.Quantity)).ForMember(d => d.LastInspectionDate, o => o.MapFrom(s => s.InventoryLine.LastInspectionDate));

Whenever I run the this code:

Mapper.Initialize(c => { c.AddProfile(new MapperProfile()); });
return context.Material.Include(i => i.InventoryLine).ProjectTo<InventoryLineViewModel>().ToList();

I get this error:

The cast to value type 'System.Decimal' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

How is that possible when all of the types that I am mapping to and from are of the same datatypes? I have even tried making the Quantity property a non-nullable in the database and in the view-model. I still get the same error.

Any help is appreciated :-)


Solution

  • The problem is that the view model Price property type is non nullable, but since the source InventoryLine is optional, EF (as suggested in the exception message) needs to be able to store a nullable value when the source is null.

    You can fix it in two ways:

    (A) Make the view model property nullable:

    public class InventoryLineViewModel
    {
        public decimal? Price { get; set; }
    }
    

    (B) Keep the view model and change the mapping as follows:

    .ForMember(d => d.Price, o => o.MapFrom(s => ((decimal?)s.InventoryLine.Price) ?? 0))
    

    or

    .ForMember(d => d.Price, o => o.MapFrom(s => s.InventoryLine != null ? s.InventoryLine.Price : 0))