代码之家  ›  专栏  ›  技术社区  ›  The Muffin Man

使用.net和SQL返回数据库行的帮助

  •  1
  • The Muffin Man  · 技术社区  · 14 年前

    我正试图以以下格式返回数据库行-类别和子类别:

    1类
    子类别
    子类别
    子类别

    类别2
    子类别
    子类别
    子类别

    换言之,返回的类别下面有属于它的子类别。

    我将类别和子类别存储在一个列表中,如果要这样做,我猜我的问题是for或foreach语法

    下面是完整的代码:

     public class Categories
        {
            public string Name { get; set; }
            public string SubName { get; set; }
        }
        public void Category()
        {
            DataTable table = new DataTable();
            DataTable subTable = new DataTable();
            List<Categories> category = new List<Categories>();
            using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["localConnectionString"].ConnectionString))
            {
                using (SqlCommand comm = new SqlCommand())
                {
                    comm.Connection = conn;
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.CommandText = "Category_Admin_GetAll";
                    conn.Open();
                    SqlDataReader reader = comm.ExecuteReader();
                    table.Load(reader);
                    reader.Close();
                    conn.Close();
                }
                using(SqlCommand comm = new SqlCommand())
                {
                    comm.Connection=conn;
                    comm.CommandType= CommandType.StoredProcedure;
                    comm.CommandText = "SubCategory_Admin_GetAll";
                    conn.Open();
                    SqlDataReader reader = comm.ExecuteReader();
                    subTable.Load(reader);
                    reader.Close();
                    conn.Close();
                }
            }
            foreach (DataRow dRow in table.Rows)
            {
                category.Add(new Categories { Name = dRow["Name"].ToString() });
            }
            foreach (DataRow dRow in subTable.Rows)
            {
                category.Add(new Categories { SubName = dRow["SubCategoryName"].ToString() });
            }
            int t = category.Count;
            resultSpan.InnerHtml += "<table class='table_category'>";
            resultSpan.InnerHtml += "<tr><td>ACTIVE</td><td>NAME</td></tr>";
            resultSpan.InnerHtml +="<tr><td></td><td>"+ category[0].Name+"</td></tr>";
                for (int i = 0; i < t; i++)
                {
                    resultSpan.InnerHtml += "<tr><td></td><td>" + category[i].SubName + "</td></tr>";
                }
            resultSpan.InnerHtml += "</table>";
        }
    
    5 回复  |  直到 14 年前
        1
  •  1
  •   Heinzi    14 年前

    首先,循环浏览所有类别。然后,在该循环中,循环遍历该类别下的所有子类别。在这里,我将数据直接输出到HTML中;如果您想填充列表,也可以填充列表。

    resultSpan.InnerHtml += "<table class='table_category'>";
    resultSpan.InnerHtml += "<tr><td>ACTIVE</td><td>NAME</td></tr>";
    
    foreach (DataRow dRow in table.Rows)
    {
        // category
        resultSpan.InnerHtml +="<tr><td></td><td>"+ dRow.Field<string>("Name") +"</td></tr>";
    
        var id = dRow.Field<int>("CategoryID");
        var subcategories = from row in subTable.AsEnumerable()
                            where row.Field<int>("CategoryID") = id
                            select row.Field<string>("SubCategoryName");
    
        foreach (string subcategory in subcategories) {
             // subcategory
             resultSpan.InnerHtml += "<tr><td></td><td>" + subcategory + "</td></tr>";
        }
    }
    
    resultSpan.InnerHtml += "</table>";
    

    当然,如果你能加入 CategoryName 给你的 subTable 存储过程,一切都变得简单(而且您不需要 table 再也没有了)。一定要 ORDER BY CategoryName ,以便具有相同类别的子类别被“组合在一起”,然后可以使用如下代码:

    resultSpan.InnerHtml += "<table class='table_category'>";
    resultSpan.InnerHtml += "<tr><td>ACTIVE</td><td>NAME</td></tr>";
    
    string lastCategory = null;
    
    foreach (DataRow dRow in subTable.Rows)
    {
        // category, if new one
        var category = dRow.Field<string>("CategoryName");
        if (category != lastCategory) {
            lastCategory = category;
            resultSpan.InnerHtml +="<tr><td></td><td>"+ category +"</td></tr>";
        }
    
        // subcategory
        resultSpan.InnerHtml += "<tr><td></td><td>" + dRow.Field<string>("SubCategoryName") + "</td></tr>";
    }
    
    resultSpan.InnerHtml += "</table>";
    
        2
  •  0
  •   Shiraz Bhaiji    14 年前

    与其他方法相比,直接使用ado.net更复杂,效率更低。

    MS引入了数据访问的实体框架,您的数据访问代码可以简化为如下内容:

    var CategoryQuery = from d in context.Category.Include("SubCategory")
                      select d;
    

    见: http://msdn.microsoft.com/en-us/data/ef.aspx

        3
  •  0
  •   RPM1984    14 年前

    你让你的生活变得更加困难。

    我推荐两样东西:

    1)照@Shiraz说的做-使用实体框架

    2)如果不可能,为什么不使用 单个存储过程 ,它基本上执行联合或联接(不完全确定您的模式/逻辑)。

    将类别合并/缝合的代码是一个数据库问题,不应该在代码中这样做。

        4
  •  0
  •   Oscar Cabrero    14 年前

    1.-如果(仅当所有类别包括所有子类别)按类别名称排序,则创建一个使两个表交叉连接的单一存储过程 2.-将category对象更改为具有类别的子集,以便可以将子类别添加到category对象中

    IEnumerable<DataRow> rows = dt.Rows.AsEnumerable();
    
    var categories = rows.Select(dr=>dr["fieldname"].ToString()).Distinct().Select(name=> new Category(){Name=name});
    var subcategories rows.Select(dr=> new Category(){ SubName =dr["subname"]});
    categories.ForEach(c=>c.SubcCategories = subcategories); 
    
        5
  •  0
  •   Jon Black    14 年前

    调用一个存储过程的C代码,该存储过程返回一个已排序的数据列表,填充一个数据表并循环它,这在极端情况下非常简单。

    C#代码

    const string DB_CONN_STR = "Server=127.0.0.1;Uid=foo_dbo;Pwd=pass;Database=foo_db;";
    
    MySqlConnection cn = new MySqlConnection(DB_CONN_STR);
    
    MySqlDataAdapter adr = new MySqlDataAdapter("category_hierarchy", cn);
    
    adr.SelectCommand.CommandType = CommandType.StoredProcedure;
    DataTable dt = new DataTable();
    adr.Fill(dt); //opens and closes the DB connection automatically !!
    
    foreach(DataRow dr in dt.Rows){
        Console.WriteLine(string.Format("{0} {1}", 
            dr.Field<uint>("cat_id").ToString(), dr.Field<string>("cat_name").ToString()));
    }
    
    cn.Dispose();
    

    使用数据表的明显好处是:轻量级、可序列化、断开连接—所有这些都允许应用程序具有性能和可扩展性。但是,如果您需要这样做的话,没有什么可以阻止您循环数据表并填充您自己的集合!

    问题的最困难部分是编写单个存储过程的代码,该存储过程按所需的顺序返回数据。就我个人而言,我将使用邻接列表方法以及存储过程和公共表表达式(CTE)来实现类别层次结构。这种方法的优点是,类别层次结构可以是多级的,编码简单,并且比其他方法(如嵌套集)更易于管理和维护。

    有关CTE的更多信息-请参阅 http://msdn.microsoft.com/en-us/library/ms190766.aspx

    不幸的是,我现在手头上只有一个MySQL实现,这个实现有点冗长,因为MySQL缺乏在RDBMS(如SQL Server(CTE)和Oracle(connect by))中使这个任务变得微不足道的特性。然而,web上有大量的资源将向您展示如何使用CTE和存储过程来完成您需要的工作。如果你对我如何在MySQL中实现这一点感兴趣,我在这个答案的底部提供了一个完整源代码的链接。

    无论您使用何种RDBMS,存储过程的结果都应该如下所示:

    call category_hierarchy();
    
    cat_id  cat_name    parent_cat_id   parent_cat_name depth
    ======  ========    =============   =============== =====
    2        Cat 1          1            Categories        1
    3        Cat 1-1        2            Cat 1             2
    4        Cat 1-2        2            Cat 1             2
    5        Cat 1-2-1      4            Cat 1-2           3
    7        Cat 2          1            Categories        1
    8        Cat 2-1        7            Cat 2             2
    9        Cat 2-2        7            Cat 2             2
    10      Cat 2-2-1      9            Cat 2-2           3
    

    我的答案的完整源代码可以在这里找到: http://pastie.org/1331218

    希望这证明你感兴趣:)

    推荐文章