如何从存储过程中填充 DataTable

27

可能重复:
如何从存储过程中检索表以填充datatable?

我正在尝试填充我的datatable。我已经创建了一个名为tmpABCD的datatable,但我需要使用存储过程中的值来填充它。我无法继续进行。

SqlConnection sqlcon = new SqlConnection(ConfigurationManager.ConnectionStrings["DB"].ConnectionString);
sqlcon.Open();
SqlCommand cmd = new SqlCommand("usp_GetABCD", sqlcon);

DataTable dt = new DataTable("tmpABCD");

dt.Columns.Add(new DataColumn("A"));
dt.Columns.Add(new DataColumn("B"));
dt.Columns.Add(new DataColumn("C"));
dt.Columns.Add(new DataColumn("D"));

1
无法操作。声望值不足。不过,这里的答案最终都变得更好了。 - MikeSmithDev
4个回答

64

您不需要手动添加列。只需使用 DataAdapter,如下所示即可简单实现:

DataTable table = new DataTable();
using(var con = new SqlConnection(ConfigurationManager.ConnectionStrings["DB"].ConnectionString))
using(var cmd = new SqlCommand("usp_GetABCD", con))
using(var da = new SqlDataAdapter(cmd))
{
   cmd.CommandType = CommandType.StoredProcedure;
   da.Fill(table);
}

请注意,您甚至不需要打开/关闭连接。这将由 DataAdapter 隐式完成。

与 SELECT 语句相关联的连接对象必须有效,但不需要打开。如果在调用 Fill 方法之前关闭了连接,则会在检索数据时打开它,然后再关闭。如果在调用 Fill 方法之前已经打开了连接,则连接将保持打开状态。


15

使用SqlDataAdapter代替,它更容易,并且您不需要自己定义列名,它将从查询结果中获取列名:

using (SqlConnection sqlcon = new SqlConnection(ConfigurationManager.ConnectionStrings["DB"].ConnectionString))
{
    using (SqlCommand cmd = new SqlCommand("usp_GetABCD", sqlcon))
    {
        cmd.CommandType = CommandType.StoredProcedure;

        using (SqlDataAdapter da = new SqlDataAdapter(cmd))
        {
            DataTable dt = new DataTable();

            da.Fill(dt);
        }
    }
}

这对我来说解决了问题。谢谢你。 - Fokwa Best

2
您可以使用SqlDataAdapter
    SqlDataAdapter adapter = new SqlDataAdapter();
    SqlCommand cmd = new SqlCommand("usp_GetABCD", sqlcon);
    cmd.CommandType = CommandType.StoredProcedure;
    adapter.SelectCommand = cmd;
    DataTable dt = new DataTable();
    adapter.Fill(dt);

1
我也是,虽然这段代码不会工作,但数据适配器应该在其构造函数中使用cmd或在命令构建后设置。在当前状态下,此数据适配器将抛出一个错误,首先告诉您连接未初始化,然后一旦您解决了这个问题,它又会告诉您选择命令没有命令文本。;] - Sean Airey
-1 没有 using 块。"两个错误不会让你得到赞同"。 - John Saunders
1
@JohnSaunders,太糟糕了,非常糟糕。回答的重点是展示可以使用DataAdapter完成此操作,而不是关于SQL连接的正确资源处理。也许我还应该解释一下硬编码SPROC名称是个坏主意?或者短变量名也不是最好的选择。而“两个错误不会得到赞同”甚至是什么意思呢? - BFree
4
@BFree: 不,你不应该发布糟糕的代码,以免一些毫无戒心的读者将其复制粘贴到他们的实际应用程序中。我也会因为糟糕的异常处理而给予反对票。 - John Saunders
这很酷,不过考虑到 OP 的利益,指出来是公平的,以防他们使用时遇到问题,然后像“啊,为什么不起作用?!”一样。没有恶意 =] - Sean Airey
2
@JohnSaunders,你太霸道了。尽管我能承受-2声望值的损失,但从原则上讲,我非常不同意。我的代码回答了问题,正确处理资源释放是每个人都应该熟悉的内容;在这个有针对性的回答中教育别人这个知识范围之外。 - BFree

2
使用SqlDataAdapter,这将简化一切。
//Your code to this point
DataTable dt = new DataTable();

using(var cmd = new SqlCommand("usp_GetABCD", sqlcon))
{
  using(var da = new SqlDataAdapter(cmd))
  {
      da.Fill(dt):
  }
}

只要您的存储过程返回一个数据集(游标),您的 DataTable 就会有您要查找的信息。

@JohnSaunders 已修复。请删除,因为我更感兴趣的是数据适配器对象而不是实现。你完全正确。 - iMortalitySX
请使用SqlDataAdapter。然后我会将其删除。 - John Saunders

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接