Linqはリストまたは単一のオブジェクトを返します
質問
次のようなLinq to Entitiesクエリがあります:
var results = from r in entities.MachineRevision
where r.Machine.IdMachine == pIdMachine
&& r.Category == (int)pCategory
select r;
通常、以下のコードを使用して、結果が返されるかどうかを確認します。
if (results.Count() > 0)
{
return new oMachineRevision(results.First().IdMachineRevision);
}
ただし、 if 条件で NotSupportedException が発生します。
エラーメッセージは次のとおりです。タイプ 'Closure type'の定数値を作成できません。このコンテキストでは、プリミティブ型( 'Int32、String、Guidなど)のみがサポートされています。
pCategory はEnum型であることに注意してください。
解決
編集:更新に基づいて、エラーはエンティティクラスの列挙に関連している可能性があります。詳細と作業については、ブログエントリをご覧ください。 -周り。クエリ構文の改善として、元の回答を残します。
FirstOrDefaultを使用してクエリ自体の最初のエンティティを選択し、結果がnullかどうかを確認してください。
int compareCategory = (int)pCategory; // just a guess
var result = (from r in entities.MachineRevision
where r.Machine.IdMachine == pIdMachine
&& r.Category == compareCategory
select r).FirstOrDefault();
if (result != null)
{
return new oMachineRevision(result.IdMachineRevision);
}
他のヒント
代わりにFirstOrDefault()を使用するだけでなく、nullをチェックするのはなぜですか?カウントを照会してから最初の要素を取得することの利点がわかりません。
linqの標準実装では、演算子<!> quot; select <!> quot;および<!> quot; where <!> quot; IEnumerableまたはIQueryableを返すメソッドにマップします。したがって、標準のlinqメソッドを使用すると、単一のオブジェクトではなく、常にクエリからIEnumerableが返されます。
ただし、linq演算子の候補であるlinqメソッドは、IEnumerablesを返すメソッドに限定されず、何でも返すメソッドを選択できます。
<!> quot; Select <!> quotという名前のインスタンスメソッドがある場合および<!> quot; Where <!> quot;クラスに固有の単一のオブジェクトまたは拡張メソッドを返し、標準のlinqの代わりに使用される単一のオブジェクトを返します。
<!> quot; Select <!> quot;または<!> quot; Where <!> quot;クラスで定義されているメソッドは、linqにIEnumerable<T>
ではなく単一の値を返すようにしています。
クエリ結果に応じて異なる匿名オブジェクトが作成されることを知りませんでした。彼らは結果がIEnumerable型であることを望んでいたと思います
foreachを使用してどうですか?
var results = from r in entities.MachineRevision
where r.Machine.IdMachine == pIdMachine
&& r.Category == pCategory
select r;
foreach( var r in results )
{
yield return new oMachineRevision( r.IdMachineRevision );
}
これは、すべての暗黙的なタイプにも当てはまります。私はこれを忘れ続けていることを認めなければなりません。それがこの投稿に出会った方法です。
お持ちの場合
class ClassA {
...
private string value;
...
public static implicit operator string(ClassA value)
{
return value.ToString();
}
...
}
比較のために明示的にクラスをastringにキャストする必要があります。
だから私は通常これを行う
var myClassAStr = myClassA.ToString();
var x = (from a in entites where a.ValToCompare == myClassAStr select a).first();
// do stuff with x
...
使用してみる
IENumerable<MachineRevision> results = from r in entities.MachineRevision
...
代わりに。
問題の原因となっている変数だと思います。
編集:
エラーメッセージを読みます。 <!> quot;タイプ 'Closure type'の定数値を作成できません。このコンテキストでは、プリミティブ型( 'Int32、String、Guidなど)のみがサポートされます。<!> quot;
これらの比較の1つは、int、string、またはguidではない型を使用することです。カテゴリを推測しています。
r.Machine.IdMachine == pIdMachine && r.Category == pCategory
興味深いことに、LinqToSqlはこの構築を許可します。 LinqToEntitiesがこれをサポートしていない理由がわかりません。
ラムダ式を使用して、別の簡単な方法でアイテムを選択することもできると思います。
var result = entities.MachineRevision
.Where(x => x.Machine.IdMachine == pIdMachine)
.Where(y => y.Category == (int)pCategory)
.FirstOrDefault();
if (result != null)
{
return new oMachineRevision(result.IdMachineRevision);
}
その後、通常どおりに続行します