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

发布于 2024-10-05 05:55:55 字数 2521 浏览 2 评论 0原文

我正在尝试以这种格式返回数据库行 - 类别和子类别:

类别 1
子类别
子类别
子类别

类别 2
子类别
子类别
SubCategory

换句话说,返回类别及其下面属于该类别的子类别。

我将类别和子类别存储在列表中,如果这是要走的路,我猜我的问题是我的 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>";
    }

I'm trying to return database rows - category and sub category in this format:

Category 1
SubCategory
SubCategory
SubCategory

Category 2
SubCategory
SubCategory
SubCategory

In other words return the category with the sub categories that belong to it underneath.

I am storing the category and sub category in a List, if this is the way to go, I'm guessing my problem is my for or foreach syntax

Here is the full code:

 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>";
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

小鸟爱天空丶 2024-10-12 05:55:56

首先,循环遍历所有类别。然后,在该循环中,循环遍历属于该类别的所有子类别。这里,我直接将数据输出为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>";

First, loop through all categories. Then, within that loop, loop through all subcategories beloging to that category. Here, I output the data directly into HTML; you can also populate a list instead, if you want to do that.

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>";

Of course, if you can just join the CategoryName to your subTable stored procedure, everything gets much easier (and you don't need table anymore). Be sure to ORDER BY CategoryName, so that subcategories with the same category are "grouped together", then you can use code like this:

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>";
孤云独去闲 2024-10-12 05:55:56

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

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

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

请参阅:http://msdn.microsoft.com/en-us/data/ef.aspx

Using ado.net directly is more complicated and less productive than other methods.

MS has introduced Entity Framework for data access, your data access code could be reduced to something like this:

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

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

吝吻 2024-10-12 05:55:56

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

我建议两件事:

1)按照@Shiraz所说的那样 - 使用实体框架

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

您用来合并/缝合类别的代码是数据库问题,您不应该在代码中执行此操作。

Your making your life more difficult than it has to be.

I'd recommend two things:

1) Do what @Shiraz says - use Entity Framework

2) If that's not possible, why not use a single stored procedure, that basically performs a UNION or JOIN (not entirely sure about your schema/logic).

The code your doing to marry up/stitch the categories is a database concern, you shouldn't be doing it in the code.

锦上情书 2024-10-12 05:55:56

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

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); 

1.- make a single store procedure that brings both tables cross joined if(only if all categories include all subcategories) order them by category name
2.- change your category object to have a subset of categories so you can add the subcategories into your category object

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); 
稚气少女 2024-10-12 05:55:56

用于调用存储过程的 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();

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

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

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

不幸的是,我现在手头只有一个 MySQL 实现,这有点啰嗦,因为 MySQL 缺乏使此任务在 RDBMS 中变得微不足道的功能,例如 SQL Server (CTE) 和 Oracle(连接经过)。但是,网络上有大量资源可以向您展示如何使用 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

希望这能引起人们的兴趣:)

The C# code for calling a stored procedure which returns a sorted list of data, populates a datatable and loops it, is simple in the extreme.

C# code

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();

The obvious benefits of using a DataTable are that it is: lightweight, serialisable, disconnected - all things that allow applications to be performant and to scale. However, there's nothing stopping you looping the datatable and populating your own collection if that's what you need to do !

The hardest part of problem is coding a single stored procedure that returns the data in the order that you require it. Personally I would implement a category hierarchy using the adjacency list method in conjunction with a stored procedure and common table expressions (CTE). The advantages of this approach are that the category hierarchy can be multi-level, it's simple to code and it's much easier to manage and maintain than other methods such as nested sets.

More info on CTE - see http://msdn.microsoft.com/en-us/library/ms190766.aspx

Unfortunately I only have a MySQL implementation to hand right now which is a little long winded as MySQL lacks the features that makes this task trivial in RDBMS such as SQL Server (CTE) and Oracle (connect by). However, there are plenty of resources on the web that will show you how to use CTE and stored procedures to do what you need. If you're interested in how I've implemented this in MySQL I've included a link to the full source at the bottom of this answer.

Whatever RDBMS you use the results of the stored procedure should be something like as follows:

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

Full source code for my answer can be found here : http://pastie.org/1331218

Hope this proves of interest :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文