我能够让我的方法(下面)在LinqPad中运行,但是当切换到我的实际代码(使用实体框架)时,我得到这个错误:
"无法强制转换类型'System '。类型'System.Object'可为空' 1'。LINQ到实体只支持转换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是可空小数。问题是这些变量可以为空,我们甚至希望通过它们为空来过滤结果。这对EF是不适用的,还是有一种优雅的方法?
编辑
要清楚,当manufacturerId作为null传入时,使用这一行返回五行(我可以通过查看DB来验证):
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,然后我得到上面的错误。
Bob Horn的注释:这个答案被接受是因为下面的Edit,指定了EF中的一个bug。这个答案的第一部分不起作用。
通过使用object.Equals(object, object)
作为比较两个值类型的方法(空值也是值类型),您隐式地将它们装箱。实体框架不支持这个
尝试使用==
操作符:
// 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。
修改当前版本:
predicate = predicate.And(scan =>
manufacturerId.HasValue
? scan.RawMaterialLabel.ManufacturerId == manufacturerId
: scan.RawMaterialLabel.ManufacturerId == null);
但如果你的应用程序允许,升级到EF5