ノート
これは、これの複製かもしれません。しかし、そこから明確な答えは得られません。
問題
linq から間違った結果が得られました。
例
id groupid status name
------------------------------------
guid1 guidA reserved truck1
guid2 guidA reserved truck2
guid3 guidA reserved truck3
guid4 guidA reserved truck4
*assume all guids are guids..
**id is a primary key (unique)
場合
結果だけを入れるwhere groupid == guidA
と正しい(4行)
しかし、結果を入れるwhere groupid == guidA && status == reserved
と間違っています(3行)
説明
式ツリーで構築されたクエリ。デバッグ ウォッチから、(間違った結果を返す) クエリは次のようになります。
query.Expression:
-----------------
Convert(value(System.Data.Objects.ObjectSet`1[myEFTable]))
.MergeAs(AppendOnly)
.Where(m => ( m.groupId == value(myFilterClass).groupId))
.Where(m => m.status.Contains(value(myFilterClass).statusStr))
.Select(m => new myViewClass()
{
Id = m.id, GroupId = m.groupid, Status = m.status, Name = m.name
})
.OrderBy(o => o.Name).Skip(0).Take(10)
次に、同様のクエリを実行しようとしましたが、正しい結果が返されます
assume e is ObjectSet<myEFTable> and strGuid is guidA
Guid grId = new Guid(strGuid);
e.AsQueryable()
.Where(m => m.status.Contains("reserved"))
.Where(m => m.groupId == grId)
.Select(m => new myViewClass()
{
Id = m.id, GroupId = m.groupid, Status = m.status, Name = m.name
}).OrderBy(o => o.Name).Skip(0).Take(10);
質問
私はこのエラーについて完全に無知です..
EF テーブルが正しく、クエリも正しいのに、間違った結果が返されるのはなぜですか?
のせい
MergeAs(AppendOnly)
でしょうか?違うのはそれだけだからです。これが一意のキーに関するものである場合
myViewClass
、すべての行が一意であり、マージされないようにするにはどうすればよいですか (その場合)。-------------------------------------------------- -------------------
2013/08/29更新
クエリの 1 つにタイプミスがあるため、結果が正しくありません。
それで、あちこちでいくつかの多くを変更した後、試行錯誤して、変更、コメント、消去の痕跡がほとんど失われるまで、突然動作します.. EUREKA!! 何?
私がしたことは、実際にはすべてを変更したわけではありません。多くの変更を加えただけですが、実際には、私が始めた場所とそれほど違いはありません。
それからその EUREKA の瞬間が終わり、私は奇跡を信じていないという理由だけで、実際に何が間違っているのかを見つけるために自分の道をたどります..
だからここにある..
表は実際には次のようになります。
PartsGroups
-----------
id name
-----------
1 Nails
-----------
Items
-----------------
id name status
-----------------
2 Table Empty
5 Table Indent
6 Door Empty
3 Sofa Empty
PartsGroupPairs
------------------
id groupId partId
------------------
1 1 4
2 1 7
3 1 8
4 1 15
-------------------
Parts
------------------------
id name itemId status
------------------------
4 XNail 2 Empty
7 SNail 5 Empty
8 UNail 6 Empty
15 ZNail 3 Empty
------------------------
関係はこんな感じ
PartsGroups PartsGroupPairs Parts Items
----------- ------------------ ------------------------ -----------------
id name id groupId partId id name itemId status id name status
----------- ------------------ ------------------------ -----------------
1 Nails 1 1 4 4 XNail 2 Empty 2 Table Empty
1 Nails 2 1 7 7 SNail 5 Empty 5 Table Indent
1 Nails 3 1 8 8 UNail 6 Empty 6 Door Empty
1 Nails 4 1 15 15 ZNail 3 Empty 3 Sofa Empty
----------- ------------------- ------------------------ -----------------
One <---> Many Many <---> One Many <------> One
PartsGroup.pairs is a collection of PartsGroupPairs
PartsGroupPair.group is a PartsGroup
PartsGroupPair.part is a Part
Part.item is an Item
Item.parts is a collection of Parts
したがって、name == 'Nails' の PartsGroup を選択すると、完全に機能し、4 行が返されます。
しかし、name == 'Nails' および Status == 'Empty' である PartsGroup を選択すると、なぜ 3 行が返されるのでしょうか?? (下記参照)
PartsGroups PartsGroupPairs Parts Items
----------- ------------------ ------------------------ -----------------
id name id groupId partId id name itemId status id name status
----------- ------------------ ------------------------ -----------------
1 Nails 1 1 4 4 XNail 2 Empty 2 Table Empty
1 Nails 3 1 8 8 UNail 6 Empty 6 Door Empty
1 Nails 4 1 15 15 ZNail 3 Empty 3 Sofa Empty
----------- ------------------- ------------------------ -----------------
この行は選択されませんでした..
PartsGroups PartsGroupPairs Parts Items
----------- ------------------ ------------------------ -----------------
id name id groupId partId id name itemId status id name status
----------- ------------------ ------------------------ -----------------
1 Nails 2 1 7 7 SNail 5 Empty 5 Table Indent
----------- ------------------- ------------------------ -----------------
私が犯した間違いはそのWhere
部分にあります。エンティティ、フィルター、ビュー、およびページング モジュールを分離するため、クエリ自体は実行時に構築されます。だからほとんど私はあちこち通り過ぎるだけIQueryable
です。
フィルターの場合、フィルターするたびに別の Where を追加します。したがって、この場合は以下のようになりました。
using(var DB = new databaseContext())
{
ObjectSet<PartsGroupPair> d =
DB.CreateObjectSet<PartsGroupPair>("partsGroupPair");
int searchGroupId = 1; // int instead of guid for example
int searchStatus = "Empty";
// filter by specific PartsGroup
IQueryable<PartsGroupPair> e = d.Where(m => m.group.id == searchGroupId);
// then if I want to filter by the status
e = e.Where(m => m.part.item.status == searchStatus)); // WRONG!!
// I want to filter by part.status, not item.status
// so instead, it should be
e = e.Where(m => m.part.status == searchStatus)); // RIGHT!!
// view
IQueryable<PartsGroupPairView> f =
e.Select(m => new PartsGroupPairView()
{
Id = m.id, GroupId = m.groupid,
Status = m.part.status, Name = m.part.name
// etc..
});
// paging
f = f.OrderBy(o => o.Name).Skip(0).Take(10);
}
不適切なフィルタリングにより、LINQ は他のパーツを無視し、2 つのパーツではなく 1 つのアイテムしか見つからなかったため、4 行ではなく 3 行を返します。
だから私の場合、それは非常に複雑なデータのばかげたタイプミスです..
すべてがうまくいっているのに、何もうまくいかないときは本当にイライラします..