Question

I was able to get my method (below) to run in LinqPad, but when switching to my actual code (using Entity Framework), I get this error:

"Unable to cast the type 'System.Nullable`1' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types."

The error occurs if I uncomment either of the two commented lines here (the actual error doesn't occur until the last line in the method is run):

public List<LotEquipmentScan> GetLotEquipmentScans(string maximoAssetNumber, decimal? manufacturerId, decimal? partNumber)
{
    var predicate = PredicateBuilder.True<LotEquipmentScanRecord>();

    // Note: Can't use == in where clause because of the possibility of nulls. That's why we're using object.Equals().
    if (maximoAssetNumber != "x") { predicate = predicate.And(scan => object.Equals(scan.MaximoAssetNumber, maximoAssetNumber)); }
    //if (manufacturerId != -1) { predicate = predicate.And(scan => object.Equals(scan.RawMaterialLabel.ManufacturerId, manufacturerId)); }
    //if (partNumber != -1) { predicate = predicate.And(scan => object.Equals(scan.RawMaterialLabel.PartNumber, partNumber)); }

    return Db.LotEquipmentScanRecords.AsExpandable().Where(predicate).ToList().Map();
}

I believe this is happening because manufacturerId and partNumber are nullable decimals. The issue is that those variables can be null, and we even want to filter the results by them being null. Does this just not work with EF, or is there an elegant way around this?

EDIT

To be clear, when manufacturerId is passed in as null, using this line returns five rows (which I can verify by looking at the DB):

if (manufacturerId != -1) { predicate = predicate.And(scan => object.Equals(scan.RawMaterialLabel.ManufacturerId, manufacturerId)); }

Using this line, no rows are returned:

if (manufacturerId != -1) { predicate = predicate.And(scan => scan.RawMaterialLabel.ManufacturerId == manufacturerId); }

The problem is when I pass in a good manufacturerId, then I get the error above.

Était-ce utile?

La solution

Edit/Note from Bob Horn: This answer was accepted because of the EDIT below, specifying a bug in EF. The first part of this answer didn't work.

By using object.Equals(object, object) as method of comparing two value types (Nullables are value types too), you are implicitly boxing them. Entity Framework does not support this.

Try using the == operator instead:

// Since scan.RawMaterialLabel.ManufacturerId and manufacturerId are both Nullable<T> of the 
// same type the '==' operator should assert value equality, whether they have a value, or not.

// (int?)1 == (int?)1
// (int?)null == (int?)null
// (int?)1 != (int?)null

predicate = predicate.And(scan => scan.RawMaterialLabel.ManufacturerId == manufacturerId);

For value types the == operator asserts value equality, similarly to what the object.Equals() does for reference types.

EDIT:

Upon further investigation, there seems to be a bug in older versions of EF (pre EF5).

Hacky fix with your current version:

predicate = predicate.And(scan => 
   manufacturerId.HasValue
     ? scan.RawMaterialLabel.ManufacturerId == manufacturerId
     : scan.RawMaterialLabel.ManufacturerId == null);

But if your application allows for it, upgrade to EF5.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top