2

LINQ for Entities (EF4 Code First) を使用していくつかのレコードを選択しようとしています。

次のような値を持つ AnimalType というフィールドを持つ Monitoring というテーブルがあります。

  • 「ライオン、トラ、ヤギ」
  • 「蛇、獅子、馬」
  • 「ガラガラヘビ」
  • "マウンテンライオン"

文字列配列 (animalValues) でいくつかの値を渡し、フィールド AnimalType の 1 つ以上の値が animalValues の 1 つ以上の値と一致する Monitorings テーブルから行を返したいと考えています。次のコードはほぼ期待どおりに機能しますが、私が取ったアプローチに重大な欠陥があることを発見しました。

public IQueryable<Monitoring> GetMonitoringList(string[] animalValues)
    {
        var result = from m in db.Monitorings
                     where animalValues.Any(c => m.AnimalType.Contains(c))
                     select m;
        return result;
    }

問題を説明するために、animalValues = { "Lion", "Tiger" } を渡すと、4 番目のレコード "Mountain Lion" に "Lion" という単語が含まれているため、3 つの行が選択されていることがわかります。マッチ。

これは私が望んでいたことではありません。「マウンテン ライオン」ではなく「ライオン」にのみ一致する「ライオン」が必要です。

別の例として、「Snake」を渡すと、「Rattlesnake」を含む行が取得されます。「Rattlesnake」に一致する「Snake」のように、その一部だけでなく、正確なコンマ区切り値に一致する一致を可能にする、より優れた LINQ コードを誰かが持っていることを願っています。

4

2 に答える 2

4

これは、作業を行う一種のハックです。

public IQueryable<Monitoring> GetMonitoringList(string[] animalValues)
{
    var values = animalValues.Select(x => "," + x + ",");
    var result = from m in db.Monitorings
                 where values.Any(c => ("," + m.AnimalType + ",").Contains(c))
                 select m;
    return result;
}

このようにして、あなたは

  • 「、ライオン、トラ、ヤギ」
  • 「、蛇、ライオン、馬、」
  • 「ガラガラヘビ」
  • "、マウンテンライオン、"

そして、",Lion" と "Mountain Lion" が一致しないことを確認します。

汚いですね、わかります。

于 2012-07-03T14:32:35.703 に答える
2

フィールド内のデータはカンマで区切られているため、これらのエントリを個別に分割する必要があります。SQL は実際には文字列を分割する方法をサポートしていないため、私が思いついたオプションは、2 つのクエリを実行することです。

最初のクエリは、最初に使用したコードを使用して、少なくとも大まかな範囲内に収まるようにし、取得するデータの量を最小限に抑えます。これを に変換しList<>て実際にクエリを実行し、結果をメモリに取り込みます。これにより、 などの拡張メソッドにアクセスできるようになりますSplit()

2 番目のクエリは、メモリ内のデータのサブセットを使用し、それをデータベース テーブルと結合して、完全に一致するものを引き出します。

public IQueryable<Monitoring> GetMonitoringList(string[] animalValues)
{
    // execute a query that is greedy in its matches, but at least
    // it's still only a subset of data. The ToList()
    // brings the data into memory, so to speak
    var subsetData = (from m in db.Monitorings
             where animalValues.Any(c => m.AnimalType.Contains(c))
             select m).ToList();

    // given that subset of data in the List<>, join it against the DB again
    // and get the exact matches this time
    var result = from data in subsetData
            join m in db.Monitorings on data.ID equals m.ID
            where data.AnimalType.Split(',').Intersect(animalValues).Any ()
            select m;        

    return result;
}
于 2012-07-03T01:54:56.307 に答える