我使用C#和SQL Server 2005,我需要一个关于如何填充对象的建议。
我有一个Customers集合,其中包含一组客户对象。每个客户对象都包含一个Orders集合,其中包含一系列订单。
我在Customers集合上使用公共Fetch()方法来填充客户及其订单。
每个连接只能打开一个DataReader,对。这意味着我需要一个连接用于'SELECT * Customers'阅读器,而当我遍历客户阅读器时,我需要为每个'SELECT * Orders WHERE CustomerId_fk = @Id'提供另一个连接。
我的问题:您是否建议我使用上述方式或仅使用简单的DataSet?
修改
我有'SELECT * Customers WHERE Id = @Id'而不是'SELECT * Customers'。
答案 0 :(得分:3)
实际上,您的断言(“每个连接只能打开一个DataReader”)不正确;您可以通过调整连接字符串enable MARS(多个活动结果集),完成工作;当然,除了你还会有很多往返(n + 1)。
我也不认为直接替代方案是数据集。就个人而言,我会使用两个结果网格(来自单个查询或2个查询)并将它们拼接回调用者。
或者,使用LINQ-to-SQL和LoadWith<Customer>(c=>c.Orders);
(DataLoadOptions
)之类的东西。即使没有LoadWith
,它也会自动执行相同的n + 1行为,只需加载每个Customer
的集合(默认情况下,懒惰地加载导航属性)。
答案 1 :(得分:2)
我可能会使用SqlDataAdapter在一次传递中查询两个DataSet。像这样:
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM CUSTOMERS WHERE CustomerId = @id; SELECT * FROM ORDERS WHERE CustomerId = @id",connection);
adapter.Fill(dataSet);
然后,我会使用以下内容设置关系:
dataSet.Relations.Add(new DataRelation("relationName", dataSet.Tables[0].Columns["CustomerId"], dataSet.Tables[1].Columns["CustomerId"]);
这样,您只需打开一个连接,查询所有数据,然后在内存中设置关系。
答案 2 :(得分:1)
我将扩展Marcs的答案。 DataReader可以同时读取多个结果集。所以你可以做到以下几点:
string sql = "SELECT * FROM Customers; SELECT * FROM Orders;";
using (SqlCommand cmd = new SqlCommand(sql, connection))
using (SqlDataReader rd = cmd.ExecuteReader())
{
while (rd.Read())
{
// Read customers
}
if (rd.NextResult()) // Change result set to Orders
{
while(rd.Read())
{
// Read orders
}
}
}
您当然只会获取所需的数据,但您明白了。这允许您使用一个命令获取两个结果集。
答案 3 :(得分:0)
该死!我只是咬我的手并使用两个连接。
请记住关闭'em和datareader。
我不知道为什么,我无法让自己在任何地方使用DataSet ......!