0

メソッド (以下) を LinqPad で実行することはできましたが、(Entity Framework を使用して) 実際のコードに切り替えると、次のエラーが発生します。

「型 'System.Nullable`1' を型 'System.Object' にキャストできません。LINQ to Entities は、EDM プリミティブまたは列挙型のキャストのみをサポートしています。」

ここでコメント化された 2 行のいずれかのコメントを外すと、エラーが発生します (実際のエラーは、メソッドの最後の行が実行されるまで発生しません)。

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 許容の 10 進数であるためだと思います。問題は、これらの変数が null になる可能性があり、それらが null であることによって結果をフィルタリングしたいことです。これは EF では機能しませんか、それともこれを回避するエレガントな方法はありますか?

編集

明確にするために、manufacturerId が null として渡された場合、この行を使用すると 5 つの行が返されます (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を渡すと、上記のエラーが発生することです。

4

1 に答える 1

3

ボブ・ホーンからの編集/メモ:この回答は、以下の編集のために受け入れられ、EF のバグが指定されました。この回答の最初の部分はうまくいきませんでした。

2 つの値型を比較す​​る方法として使用することによりobject.Equals(object, object)(Nullable も値型です)、暗黙的にそれらをボックス化しています。Entity Framework はこれをサポートしていません。

==代わりに演算子を使用してみてください。

// 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 より前) にバグがあるようです。

現在のバージョンでのハック修正:

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

ただし、アプリケーションで許可されている場合は、EF5 にアップグレードしてください。

于 2012-12-21T21:38:58.220 に答える