我能够在LinqPad中运行我的方法(下面),但是当切换到我的实际代码(使用Entity Framework)时,我收到此错误:
“无法将类型'System.Nullable`1'强制转换为'System.Object'。 LINQ to Entities仅支持转换EDM原语或枚举 类型“。
如果我在这里取消注释两条注释行中的任何一条(在方法的最后一行运行之前不会发生实际错误),则会发生错误:
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();
}
我相信这种情况正在发生,因为manufacturerId和partNumber是可以为空的小数。问题是那些变量可以为空,我们甚至想要将结果过滤为null。这不适用于EF,还是有一种优雅的方式呢?
修改
要明确的是,当manufacturerId作为null传入时,使用此行返回五行(我可以通过查看数据库来验证):
if (manufacturerId != -1) { predicate = predicate.And(scan => object.Equals(scan.RawMaterialLabel.ManufacturerId, manufacturerId)); }
使用此行,不返回任何行:
if (manufacturerId != -1) { predicate = predicate.And(scan => scan.RawMaterialLabel.ManufacturerId == manufacturerId); }
问题是当我传入一个好的manufacturerId时,我得到上面的错误。
答案 0 :(得分:3)
来自Bob Horn的编辑/备注:由于下面的编辑,此答案已被接受,指定了EF中的错误。这个答案的第一部分没有用。
通过使用object.Equals(object, object)
作为比较两种值类型的方法(Nullables也是值类型),您将隐式装箱。实体框架不支持此功能。
请尝试使用==
运算符:
// 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);
对于值类型,==
运算符断言值相等,类似于object.Equals()对引用类型的作用。
修改强>
经过进一步调查,旧版EF(前EF5)似乎有bug。
Hacky修复了您当前的版本:
predicate = predicate.And(scan =>
manufacturerId.HasValue
? scan.RawMaterialLabel.ManufacturerId == manufacturerId
: scan.RawMaterialLabel.ManufacturerId == null);
但如果您的应用程序允许,请升级到EF5。