使用表名访问DataSet中的DataTables

问题描述 投票:0回答:1

我目前正在编写一个程序,它从 SQL 接收 3 个表,其中包含我正在使用的每个表中的数据,并通过行来创建相应类的对象。

经过一步一步的调试,我可以看到DataSet中的数据确实是正确的,但我似乎无法通过名称访问它。 当我使用索引访问数据集中的表时,它工作得很好,就像这样 -

DataSet ds = new ProgramProcedures().GetTestByUser(UserId);                                    
if (ds.Tables[0].IsHasRows())
{
    foreach (DataRow _dr in ds.Tables[0].Rows)
    {
        TestList.Add(new Test(_dr));
    }
}

当我尝试按名称访问它时,它失败并且不输入 if 语句。

DataSet ds = new ProgramProcedures().GetTestByUser(UserId);
if (ds.Tables["Name1"].IsHasRows())
{
    foreach (DataRow _dr in ds.Tables["Name1"].Rows)
    {
        TestList.Add(new Test(_dr));
    }
}

在存储过程中,数据来自我包含以下几行 -

@tables nvarchar(max)='' output
set @tables='Name1,Name2,Name3'

调试检查ds变量内容时,数据正确,但表名是“Table, Table1, Table2” 我究竟做错了什么?我想按名称访问表,因为它使代码在对其或过程进行任何更改时更加可靠。

我尝试使用表的索引而不是它们的名称,这非常有效,但我想使用表的名称。

c# .net datatable dataset
1个回答
0
投票

表名称是根据数据集中的表数量自动生成的,因此您的输出参数不会自动映射。我也不知道你在哪里消费它。

我创建了一个示例 DB 和 SP,它运行没有问题:

CREATE PROCEDURE GetTestByUser 
    -- Add the parameters for the stored procedure here
    @UserId int, 
    @TableNames nvarchar(max) = '' OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    set @TableNames ='Table1,Table2'

    -- Insert statements for procedure here
    SELECT * FROM Table1
    SELECT * FROM Table2
END
GO

您需要使用数据才能检索输出参数。因此,要么显式关闭

SqlDataReader
,要么使用像
SqlDataAdapter.Fill
这样的内置方法在最后关闭连接:

using SqlConnection con = new(connectionString);
using SqlCommand command = new("dbo.GetTestByUser", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@UserId", 1);
SqlParameter tableNamesOutParameter = new("@TableNames", SqlDbType.NVarChar, 1000)
{ Direction = ParameterDirection.Output };
command.Parameters.Add(tableNamesOutParameter);

DataSet ds = new();
using SqlDataAdapter da = new(command);
da.Fill(ds);
string[] tableNames = tableNamesOutParameter.Value?.ToString()?.Split(',', StringSplitOptions.TrimEntries) ?? Array.Empty<string>();
for (int i = 0; i < tableNames.Length; i++)
{
    ds.Tables[i].TableName = tableNames[i];
}

// now you can access each table by the correct name:
DataTable? table1 = ds.Tables["Name1"];
if (table1?.AsEnumerable().Any() == true)
{
    foreach (DataRow _dr in table1.Rows)
    {
        TestList.Add(new Test(_dr));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.