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

automapper c# entity-framework-6

Question

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 :-)

1
2
12/14/2016 6:37:38 PM

Accepted Answer

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))
10
12/14/2016 7:19:42 PM

Popular Answer

.NET 4.0, Nullable has a "GetValueOrDefault()" method. So if you cast the query to Nullable, then you can end up with the correct Type when complete. This method will also generate the correct single SQL SELECT SUM query and is faster than other solutions that return the entire recordset to later sum via linq

decimal result = ((decimal?)query.Where(w => w.Customer =="ABC").Sum(s =>  (decimal?)s.Amount)).GetValueOrDefault();


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