3

ノート

これは、これの複製かもしれません。しかし、そこから明確な答えは得られません。

問題

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);

質問

私はこのエラーについて完全に無知です..

  1. EF テーブルが正しく、クエリも正しいのに、間違った結果が返されるのはなぜですか?

  2. のせいMergeAs(AppendOnly)でしょうか?違うのはそれだけだからです。

  3. これが一意のキーに関するものである場合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 行を返します。

だから私の場合、それは非常に複雑なデータのばかげたタイプミスです..

すべてがうまくいっているのに、何もうまくいかないときは本当にイライラします..

4

0 に答える 0