Sql server 2008 将数千条记录和数十万条子记录拉入类对象最有效的方法是什么?
我有一个场景,需要提取大约7500条数据库记录,其中每条记录有6个子实体列表。每个子列表可以是0到大约125条记录 我的班级结构是这样的: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
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
方法。这只需要对数据库进行一次点击,但不会将整个数据集读入内存。