使用Entity Framework,哪种方法更有效?

时间:2012-06-12 10:05:42

标签: c# linq entity-framework

我有一些代码可以在循环内更改数据库中某些数据的值。我只是想知道最先过滤数据的最有效方法是什么?我举个例子: -

上课: -

public class myObj 
{
    int id {get;set;}
    string product {get; set;}
    string parent{get;set;}
    int 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;
}

或者没有区别?

2 个答案:

答案 0 :(得分:2)

不确定如何编译上面的代码示例。

myObj对象中,received属性为int,但您正在根据bool对其进行评估,这会导致此行o.received != true导致错误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;
    }
}

使用类似于此的Stopwatch对每个方法迭代x次的方法:

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....
}

答案 1 :(得分:0)

如果您在两个查询之间进行选择,我同意它们都会执行相似的操作,并且基准测试是一个合适的响应。但是,您可以执行一些优化操作。例如,您可以使用方法&#39; AsEnumerable&#39;使用IEnumerable&#39; Where&#39;强制评估。 LINQ&#39; Where&#39;子句(转换为SQL并针对数据源执行或处理对象层次结构中的位置的差异)。由于您似乎只操作属性(而不是实体关系),因此您可以这样做:

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

这样做可以避免每个记录命中数据库(可能避免网络延迟),但会增加内存占用。这是associated LINQ further explaining this idea。这实际上取决于你可以吸收性能成本的地方。