1

ループ内でデータベース内の一部のデータの値を変更するコードがあります。最初にデータをフィルタリングする最も効率的な方法は何ですか? 例を挙げます:-

クラスで: -

public class myObj 
{
    int id {get;set;}
    string product {get; set;}
    string parent{get;set;}
    bool received {get;set;}
}

そしてDbContext:-

public class myCont:DbContext
{
    public DbSet<myObj> myObjs {get;set;}
}

これを行う方が良いですか:-

int[] list;
/* Populate list with a bunch of id numbers found in myOBjs */
myCont data = new myCont();
myObj ob = data.myObjs.Where(o => o.parent == "number1");
foreach(int i in list)
{
    ob.First(o => o.id == i && o.received != true).received = true;
}

または:-

int[] list;
/* Populate list with a bunch of id numbers found in myOBjs */
myCont data = new myCont();
foreach(int i in list)
{
    data.myObjs.First(o => o.parent == "number1" && o.id == i && o.received != true).received = true;
}

それとも違いはありませんか?

4

2 に答える 2

2

上記のコード例をコンパイルする方法がわかりません。

あなたのmyObjオブジェクトでは、receivedプロパティはintですが、それを に対して評価しているため、boolこの行o.received != trueはエラーになりますCannot apply operator '!=' to operands of type 'int' and 'bool'

SQL をチェックするに
は コードがコンパイルされたら、SQL プロファイラを使用して、生成された SQL を確認します。

構築されたSQLが表示されます

ベンチマーク
以下は、コード実行のベンチマークを実行できる1 つの方法のみを大雑把に説明したものです。

コードをメソッドにラップします。次に例を示します。

public void TestingOperationOneWay()
{
    int[] list;
    /* Populate list with a bunch of id numbers found in myOBjs */
    myCont data = new myCont();
    myObj ob = data.myObjs.Where(o => o.parent == "number1");
    foreach(int i in list)
    {
        ob.First(o => o.id == i && o.received != true).received = true;
    }
}

と:

public void TestingOperationAnotherWay()
{
    int[] list;
    /* Populate list with a bunch of id numbers found in myOBjs */
    myCont data = new myCont();
    foreach(int i in list)
    {
        data.myObjs.First(o => o.parent == "number1" && o.id == i && o.received != true).received = true;
    }
}

次のようなメソッドを使用して、各メソッドを x 回反復するメソッドを作成しStopwatchます。

private static TimeSpan ExecuteOneWayTest(int iterations)
{
    var stopwatch = Stopwatch.StartNew();

    for (var i = 1; i < iterations; i++)
    {
        TestingOperationOneWay();
    }

    stopwatch.Stop();

    return stopwatch.Elapsed;
}

次のような結果を評価します。

static void RunTests()
{
    const int iterations = 100000000;

    var timespanRun1 = ExecuteOneWayTest(iterations);
    var timespanRun2 = ExecuteAnotherWayTest(iterations);

    // Evaluate Results....
}
于 2012-06-12T10:54:04.673 に答える
0

2 つのクエリから選択する場合、どちらも同様に実行されることに同意します。ベンチマークは適切な応答です。ただし、最適化するためにできることがいくつかあります。たとえば、メソッド 'AsEnumerable' を使用して、IEnumerable 'Where' を LINQ 'Where' 句の代わりに使用して評価を強制することができます (SQL に変換してデータ ソースに対して実行するか、オブジェクト階層内の where を処理するという違いがあります)。プロパティのみを操作しているように見えるため(エンティティ関係は操作していないようです)、次のようにすることができます。

int[] list;
/* Populate list with a bunch of id numbers found in myOBjs */
myCont data = new myCont();
myObj ob = data.myObjs.Where(o => o.parent == "number1").AsEnumerable<myObj>();
foreach(int i in list)
{
    ob.First(o => o.id == i && o.received != true).received = true;
}

そうすることで、レコードごとにデータベースにヒットするというペナルティを回避できます (おそらくネットワーク遅延を回避できます) が、メモリ フットプリントが増加します。これは、このアイデアをさらに説明する関連する LINQです。それは、パフォーマンス コストをどこで吸収できるかに大きく依存します。

于 2012-06-12T11:58:53.673 に答える