Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 将数千条记录和数十万条子记录拉入类对象最有效的方法是什么?_Sql Server 2008_C# 4.0_Data Access - Fatal编程技术网

Sql server 2008 将数千条记录和数十万条子记录拉入类对象最有效的方法是什么?

Sql server 2008 将数千条记录和数十万条子记录拉入类对象最有效的方法是什么?,sql-server-2008,c#-4.0,data-access,Sql Server 2008,C# 4.0,Data Access,我有一个场景,需要提取大约7500条数据库记录,其中每条记录有6个子实体列表。每个子列表可以是0到大约125条记录 我的班级结构是这样的: public class Entity { public int ID { get; set; public string Name { get; set; } public ICollection<ChildEntity1> Children1 { get; set; } public ICollection&l

我有一个场景,需要提取大约7500条数据库记录,其中每条记录有6个子实体列表。每个子列表可以是0到大约125条记录

我的班级结构是这样的:

public class Entity
{
    public int ID { get; set;
    public string Name { get; set; }
    public ICollection<ChildEntity1> Children1 { get; set; }
    public ICollection<ChildEntity2> Children2 { get; set; }
    public ICollection<ChildEntity3> Children3 { get; set; }
    public ICollection<ChildEntity4> Children4 { get; set; }
    ... 2 more collections
}
公共类实体
{
公共int ID{get;set;
公共字符串名称{get;set;}
公共ICollection Children1{get;set;}
公共ICollection Children2{get;set;}
公共ICollection Children3{get;set;}
公共ICollection子项4{get;set;}
…还有两个系列
}
在检索所有实体之后,我需要迭代每个实体并执行一些计算,调用一些web服务和其他各种内容,最终导出到一个文件

使用c#4从MS Sql Server 2008检索此数据的最佳策略是什么?使用DataAdapters的数据集是最佳方法吗?ORM


出于明显的原因,我不想选择N+1方案。

因此,我最终使用了一个嵌套的DataReader,一个外部的DataReader用于父实体获取所有父实体,然后一个内部的DataReader使用reader.NextResult()方法读取一条语句中的所有子实体,类似如下:

DECLARE CURSOR on the Entity.

OPEN CURSOR.

For each FETCH CURSOR

    SELECT the child rows for the current Entity.

    Write the output.

CLOSE CURSOR.
var exampleSql = "select * from child1Table; " +
                 "select * from child2Table; " +
                 "select * from child3Table"; 
                 // and so on for the other child tables
using (var outerReader = cmd.ExecuteReader())
{
    while (outerReader.Read())
    {
        var entity = new Entity();
        entity.Prop1 = outerReader[0];
        entity.Prop2 = outerReader[1];
        //.... etc.

        using (var cmdInner = new SqlCommand(exampleSql))
        using (var innerReader = cmdInner.ExecuteReader())
        {
            while (innerReader.Read())
            {
                var child = new Child1();
                child.Prop1 = innerReader[0];
                // ... etc.
                entity.Children1.Add(child);
            }
            innerReader.NextResult();
            while (innerReader.Read())
            {
                var child = new Child2();
                child.Prop1 = innerReader[0];
                // ... etc.
                entity.Children2.Add(child);
            }
            innerReader.NextResult();
            // and so on for the other child entities
        }
    }
}
至少通过这种方式,我只向数据库发送一条sql语句来检索每个父项的所有子实体,而不是每个子项和每个父项单独发送一条语句

如果有更好的方法,请随时告诉我。


顺便说一句,我的示例代码只是伪代码。真正的东西是使用参数化查询,没有选择星,只有我需要的列。目的是显示方法,而不是实际的实现。

所以我最终做的是使用嵌套的数据读取器,一个外部读取器让父实体获取所有父实体,然后一个内部读取器使用reader.NextResult()方法读取一条语句中所有子语句的函数,类似于:

var exampleSql = "select * from child1Table; " +
                 "select * from child2Table; " +
                 "select * from child3Table"; 
                 // and so on for the other child tables
using (var outerReader = cmd.ExecuteReader())
{
    while (outerReader.Read())
    {
        var entity = new Entity();
        entity.Prop1 = outerReader[0];
        entity.Prop2 = outerReader[1];
        //.... etc.

        using (var cmdInner = new SqlCommand(exampleSql))
        using (var innerReader = cmdInner.ExecuteReader())
        {
            while (innerReader.Read())
            {
                var child = new Child1();
                child.Prop1 = innerReader[0];
                // ... etc.
                entity.Children1.Add(child);
            }
            innerReader.NextResult();
            while (innerReader.Read())
            {
                var child = new Child2();
                child.Prop1 = innerReader[0];
                // ... etc.
                entity.Children2.Add(child);
            }
            innerReader.NextResult();
            // and so on for the other child entities
        }
    }
}
至少通过这种方式,我只向数据库发送一条sql语句来检索每个父项的所有子实体,而不是每个子项和每个父项单独发送一条语句

如果有更好的方法,请随时告诉我。


顺便说一句,我的示例代码只是伪代码。真正的代码是使用参数化查询,没有选择星型,只有我需要的列。目的是显示方法,而不是实际的实现。

您需要同时在内存中显示所有实体,还是可以提取实体的子集,处理它们,然后将它们写入文件?例如,您的策略不应该是“检索所有实体”,然后是“迭代每个实体”。有没有什么原因使您的算法不能按一次一行的方式运行?@Gilbert-可以提取一个子集,比如说一次100,然后处理并添加到列表中,最后导出。父实体及其子实体是完全原子的。@Kirk-按一次一行的方式运行需要我访问数据库~45000次数(7500个父记录*6个子集合)。我想这就是我的问题所在,有没有更有效的方法?@Chris,我不是这个意思。例如,如果你只是简单地使用ADO.NET并获取IDataReader,你可以为每一行调用
Read
方法。这只需要对数据库进行一次点击,但不会将整个数据集读入内存。你需要所有的实体吗同时在内存中,或者您可以获取实体的子集、处理它们并将它们写入文件吗?首先,您的策略不应该是“检索所有实体”,然后“迭代每个实体”。有没有什么原因使您的算法不能按一次一行的方式运行?@Gilbert-可以提取一个子集,比如说一次100,然后处理并添加到列表中,最后导出。父实体及其子实体是完全原子的。@Kirk-按一次一行的方式运行需要我访问数据库~45000次数(7500个父记录*6个子集合)。我想这就是我的问题所在,有没有更有效的方法?@Chris,我不是这个意思。例如,如果你只是简单地使用ADO.NET并获取一个IDataReader,你就可以为每一行调用
Read
方法。这只需要对数据库进行一次点击,但不会将整个数据集读入内存。