如何从SqlDataReader填充集合属性?

时间:2016-06-29 12:44:58

标签: sql ado.net mapping left-join sqldatareader

我有这个简单的SQL查询:

SELECT  CustomerName, OrderId 
FROM    Customer c
        LEFT JOIN Orders o ON o.CustomerId = c.CustomerId

我需要从查询结果中填充我的Customer实体:

public class Customer
 {
    public string Name { get; set; }
    public IEnumerable<int> OrderIds { get; set; }
 }

我正在使用SqlDataReader读取数据:

using(SqlDataReader rdr = cmd.ExecuteReader())
{      
    while (rdr.Read())
    {
     Customer c = new Customer();
     c.Name = rdr["CustomerName"].ToString();      
     yield return c;
    }
}

问题:在不使用ORM的情况下,填写 OrderIds 属性的最简单,最简洁的方法是什么?左连接导致查询返回每个客户多行(因为每个客户有多个订单)所以现在逐行读取它就像上面的代码一样不起作用?有没有办法填充该实体,仍然使用收益率返回延期执行?

3 个答案:

答案 0 :(得分:2)

第一版:

var customersRDR = from rCustomers in rdr.Cast<DbDataRecord>()
                   group rCustomers by rCustomers["CustomerName"] into custGroups
                   select new Customer
                   {
                      Name = (string)custGroups.Key,
                      OrderIds = from c in custGroups select (Int32)c["OrderId"]
                   };


第二版:

DataTable dt = new DataTable();
dt.Load(rdr);

var customers = from c in dt.AsEnumerable()
                group c by c["CustomerName"] into custGroups
                select new Customer{
                   Name = custGroups.Key.ToString(),
                   OrderIds = from c in custGroups select Convert.ToInt32(c["OrderId"])
               };


第3版:

DataTable dt = new DataTable();
dt.Load(rdr);

var customerGroups = dt.AsEnumerable()
                     .GroupBy(c => c["CustomerName"]);

foreach (var customer in customerGroups){
     Customer cust = new Customer();
     cust.Name = customerGroup.Key.ToString();
     cust.OrderIds = from c in customerGroup select Convert.ToInt32(c["OrderId"]);
    }

答案 1 :(得分:1)

List<int> orderIds = (from IDataRecord r in rdr
                      where (string) r["CustomerName"] == c.Name
                      select (int)r["OrderIds"]).ToList();

修改

如果没有ORM,这有点棘手。然而,另一种选择是使用多个阅读器。它需要您有两个查询 - 一个用于客户,一个用于订单。举个例子:

    private void GetCustomerWithOrders()
    {
        using (var conn = new SqlConnection("your connection string"))
        {
            using (var cmd = conn.CreateCommand())
            {
                conn.Open();
                cmd.CommandText = "SELECT CustomerName, CustomerId FROM Customer";
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var customerId = reader.GetInt32(1); // CustomerId
                        List<int> orders = GetOrders(customerId);
                    }
                }
            }
        }
    }

    private List<int> GetOrders(int customerId)
    {
        var orders = new List<int>();
        using (var conn = new SqlConnection("your connectionstring"))
        {
            using (var cmd = new SqlCommand("SELECT OrderId FROM Orders WHERE CustomerId = @CustomerId", conn))
            {
                var param = new SqlParameter
                {
                    ParameterName = "@CustomerId",
                    Value = customerId
                };

                cmd.Parameters.Add(param);
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var orderId = reader.GetInt32(0); // OrderId
                        orders.Add(orderId);
                    }
                }
            }
        }

        return orders;
    }

答案 2 :(得分:0)

var dataReader = cmd.ExecuteReader();

var dataTable = new DataTable();

dataTable.Load(dataReader);