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属性是 an int,但您正在根据 a 评估它,bool这应该会导致该行o.received != true导致 error Cannot apply operator '!=' to operands of type 'int' and 'bool'

检查 SQL
代码编译后,使用SQL Profiler查看生成的 SQL。

这将向您展示构建的 SQL

基准测试
下面是对您可以对代码执行进行基准测试的一种可能方法的非常粗略的描述。

将您的代码包装到一个方法中,例如:

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

在您的两个查询之间进行选择的情况下,我同意它们都会以类似的方式执行,并且基准测试是一个适当的响应。但是,您可以做一些事情来优化。例如,您可以使用方法 '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 回答