Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我可以使用什么强类型数据结构来保存具有不同形状的多个记录集的集合_C#_Data Structures_Recordset_Strong Typing - Fatal编程技术网

C# 我可以使用什么强类型数据结构来保存具有不同形状的多个记录集的集合

C# 我可以使用什么强类型数据结构来保存具有不同形状的多个记录集的集合,c#,data-structures,recordset,strong-typing,C#,Data Structures,Recordset,Strong Typing,在回答我最初问题的人的要求下,我被要求改写这个问题,以便弄清实际需求的底细 我可以使用什么强类型数据结构来保存多个记录集的集合,其中每个记录集将包含与其他记录集形状不同的行 这种需求是由处理通过DbDataReader从存储过程返回的数据的需求驱动的。存储过程可能有多个记录集,每个记录集返回不同的列和列数 将有DTO类来表示相应数据集的每一行。这些是在编译时已知的。我需要的是一个数据结构,它可以保存多个记录集,并且对于每个记录集保存表示从记录集返回的行的DTO 存储过程示例: CREATE PR

在回答我最初问题的人的要求下,我被要求改写这个问题,以便弄清实际需求的底细

我可以使用什么强类型数据结构来保存多个记录集的集合,其中每个记录集将包含与其他记录集形状不同的行

这种需求是由处理通过DbDataReader从存储过程返回的数据的需求驱动的。存储过程可能有多个记录集,每个记录集返回不同的列和列数

将有DTO类来表示相应数据集的每一行。这些是在编译时已知的。我需要的是一个数据结构,它可以保存多个记录集,并且对于每个记录集保存表示从记录集返回的行的DTO

存储过程示例:

CREATE PROCEDURE [dbo].[MultipleRecordSetStoredProcedure]
    @Id                 INT
,   @Name               VARCHAR(20)
,   @Active             BIT
,   @Price              DECIMAL(10, 4)
,   @UniqueIdentifier   UNIQUEIDENTIFIER
,   @Count              TINYINT
AS
BEGIN
    /* First Record Set */
    SELECT 
        @Id AS Id
    ,   @Name AS Name
    UNION
    SELECT
        17 AS Id
    ,   'Bill' AS Name;

    /* Second Record Set */
    SELECT 
        @Name AS Name,
        @Active as Active
    UNION
    SELECT
        'Bill' AS Name
    ,   CAST(0 AS BIT) AS Active;

    /* Third Record Set */
    SELECT
        @UniqueIdentifier   AS UNIQUEIDENTIFIER
    ,   @Count              AS Count
    UNION
    SELECT
        NEWID() AS UNIQUEIDENTIFIER
   ,    CAST(10 AS TINYINT) AS Count;
END
调用代码示例:

DbConnection connection = CreateConnection();
CommandBehavior commandBehavior = CommandBehavior.Default;

// Create a command to execute the stored storedProcedure
using (DbCommand command = connection.CreateStoredProcedureCommand(
    procedureName,
    procedureParameters,
    commandTimeout,
    transaction))
{
    // Populate a DataReder by calling the command
    using (DbDataReader reader = command.ExecuteReader(commandBehavior))
    {
        // Iterate through each result set...
        do
        {
            // Process the result set line by line
            while (reader.Read())
            {   
                // Read data into DataStructure
            }

        } while (reader.NextResult());
    }    
}
此处的DTO示例:

internal class MultipleRecordSetStoredProcedureReturnType1
{
    public int Id { get; set; }
    public string Name { get; set; }
}

internal class MultipleRecordSetStoredProcedureReturnType2
{
    public bool Active { get; set; }
    public decimal Decimal { get; set; }
}

internal class MultipleRecordSetStoredProcedureReturnType3
{
    public Guid UniqueIdentifier { get; set; }
    public Byte Count { get; set; }
}

理想情况下,我不想要对象列表动态列表,而是想要记录集内容的DTO列表。希望这能更好地澄清我的原始问题。

阅读了原始问题和这一个问题后,听起来你最终会得到一个列表,其中包含其他列表,每个列表都有自己的类型。在遍历列表时,您将不知道内部列表的类型,因为它是可变的。考虑到这一点,您将不可避免地必须测试该类型,然后强制转换它,例如

foreach(var resultset in resultsets)
{
    if(resultset is MultipleRecordSetStoredProcedureReturnType1)
        //... cast it and do something...
}
考虑到你将不可避免地要测试内在类型和演员阵容,即使你能实现你的目标,我也不确定它最终会起到什么作用。这张单子也可以是

List<List<Object>>
列表
或许

List<List<IResultSet>>
列表

根据最后的示例,您可以考虑为内部类型定义接口,以确保只从该接口继承的对象包含在该接口中。即使界面没有定义任何行为,只是一个简单的声明,这也可能是有益的。

阅读了原始问题和这一个问题后,听起来您最终会得到一个列表,其中包含其他列表,每个列表都有自己的类型。在遍历列表时,您将不知道内部列表的类型,因为它是可变的。考虑到这一点,您将不可避免地必须测试该类型,然后强制转换它,例如

foreach(var resultset in resultsets)
{
    if(resultset is MultipleRecordSetStoredProcedureReturnType1)
        //... cast it and do something...
}
考虑到你将不可避免地要测试内在类型和演员阵容,即使你能实现你的目标,我也不确定它最终会起到什么作用。这张单子也可以是

List<List<Object>>
列表
或许

List<List<IResultSet>>
列表

根据最后的示例,您可以考虑为内部类型定义接口,以确保只从该接口继承的对象包含在该接口中。即使接口没有定义任何行为,只是一个简单的声明,这也可能是有益的。

我不确定返回包含不同结果的
列表是否有意义。我可能会创建一个包装器类来将dto对象分组,如下所示

public class RecordSetContainer
{
    public RecordSetContainer()
    {
        RecordSet1 = new List<MultipleRecordSetStoredProcedureReturnType1>();
        RecordSet2 = new List<MultipleRecordSetStoredProcedureReturnType2>();
        RecordSet3 = new List<MultipleRecordSetStoredProcedureReturnType3>();
    }
    public List<MultipleRecordSetStoredProcedureReturnType1> RecordSet1 { get; set; }
    public List<MultipleRecordSetStoredProcedureReturnType2> RecordSet2 { get; set; }
    public List<MultipleRecordSetStoredProcedureReturnType3> RecordSet3 { get; set; }
}

我不确定返回包含不同结果的
列表是否有意义。我可能会创建一个包装器类来将dto对象分组,如下所示

public class RecordSetContainer
{
    public RecordSetContainer()
    {
        RecordSet1 = new List<MultipleRecordSetStoredProcedureReturnType1>();
        RecordSet2 = new List<MultipleRecordSetStoredProcedureReturnType2>();
        RecordSet3 = new List<MultipleRecordSetStoredProcedureReturnType3>();
    }
    public List<MultipleRecordSetStoredProcedureReturnType1> RecordSet1 { get; set; }
    public List<MultipleRecordSetStoredProcedureReturnType2> RecordSet2 { get; set; }
    public List<MultipleRecordSetStoredProcedureReturnType3> RecordSet3 { get; set; }
}

在这种情况下,我认为最好保持简单

  • 您有一个返回3个结果集的存储过程,因此创建一个包含这3个结果集的模型
  • 要填充
    ResultModel
    ,最好使用
    SqlDataAdapter
    DataSet
    。它使事情变得非常简单,比数据读取器更容易
  • 结果模型的代码:

    public class ResultModel
    {
        public List<Type1> List1 { get; set; }
        public List<Type2> List2 { get; set; }
        public List<Type3> List3 { get; set; }
    }
    
    public class Type1
    {
        public int A { get; set; }
    }
    public class Type2
    {
        public int B { get; set; }
        public string C { get; set; }
    }
    public class Type3
    {
        public int D { get; set; }
        public string E { get; set; }
        public string F { get; set; }
    }
    
    public ResultModel GetData()
    {
        var connection = @"data source=(localdb)\v11.0;initial catalog=TestDB;integrated security=True;MultipleActiveResultSets=True;";
        var command = "dbo.Procedure";
        var tableAdapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
        tableAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
        var dataSet = new DataSet();
        tableAdapter.Fill(dataSet); 
    
        var t1 = dataSet.Tables[0].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type1
            {
                A = row.Field<int>("A"),
            }).ToList();
    
        var t2 = dataSet.Tables[1].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type2
            {
                B = row.Field<int>("B"),
                C = row.Field<string>("C")
            }).ToList();
    
        var t3 = dataSet.Tables[1].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type3
            {
                D = row.Field<int>("D"),
                E = row.Field<string>("E"),
                F = row.Field<string>("F")
            }).ToList();
    
        var result = new ResultModel() { List1 = t1, List2 = t2, List3 = t3 };
    
        return result;
    }
    
    您可以使用SqlDataAdapter和DataSet填充结果模型:

    public class ResultModel
    {
        public List<Type1> List1 { get; set; }
        public List<Type2> List2 { get; set; }
        public List<Type3> List3 { get; set; }
    }
    
    public class Type1
    {
        public int A { get; set; }
    }
    public class Type2
    {
        public int B { get; set; }
        public string C { get; set; }
    }
    public class Type3
    {
        public int D { get; set; }
        public string E { get; set; }
        public string F { get; set; }
    }
    
    public ResultModel GetData()
    {
        var connection = @"data source=(localdb)\v11.0;initial catalog=TestDB;integrated security=True;MultipleActiveResultSets=True;";
        var command = "dbo.Procedure";
        var tableAdapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
        tableAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
        var dataSet = new DataSet();
        tableAdapter.Fill(dataSet); 
    
        var t1 = dataSet.Tables[0].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type1
            {
                A = row.Field<int>("A"),
            }).ToList();
    
        var t2 = dataSet.Tables[1].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type2
            {
                B = row.Field<int>("B"),
                C = row.Field<string>("C")
            }).ToList();
    
        var t3 = dataSet.Tables[1].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type3
            {
                D = row.Field<int>("D"),
                E = row.Field<string>("E"),
                F = row.Field<string>("F")
            }).ToList();
    
        var result = new ResultModel() { List1 = t1, List2 = t2, List3 = t3 };
    
        return result;
    }
    
    public ResultModel GetData()
    {
    var connection=@“数据源=(localdb)\v11.0;初始目录=TestDB;集成安全性=True;MultipleActiveResultSets=True;”;
    var command=“dbo.Procedure”;
    var tableAdapter=new System.Data.SqlClient.SqlDataAdapter(命令,连接);
    tableAdapter.SelectCommand.CommandType=CommandType.StoredProcess;
    var数据集=新数据集();
    tableAdapter.Fill(数据集);
    var t1=dataSet.Tables[0]。Rows.Cast()
    .ToList().Select(行=>新类型1
    {
    A=行字段(“A”),
    }).ToList();
    var t2=dataSet.Tables[1]。Rows.Cast()
    .ToList().Select(行=>新类型2
    {
    B=行字段(“B”),
    C=行字段(“C”)
    }).ToList();
    var t3=dataSet.Tables[1]。Rows.Cast()
    .ToList().Select(行=>新类型3
    {
    D=行字段(“D”),
    E=行字段(“E”),
    F=行字段(“F”)
    }).ToList();
    var result=new ResultModel(){List1=t1,List2=t2,List3=t3};
    返回结果;
    }
    
    这里的要点是:

    public class ResultModel
    {
        public List<Type1> List1 { get; set; }
        public List<Type2> List2 { get; set; }
        public List<Type3> List3 { get; set; }
    }
    
    public class Type1
    {
        public int A { get; set; }
    }
    public class Type2
    {
        public int B { get; set; }
        public string C { get; set; }
    }
    public class Type3
    {
        public int D { get; set; }
        public string E { get; set; }
        public string F { get; set; }
    }
    
    public ResultModel GetData()
    {
        var connection = @"data source=(localdb)\v11.0;initial catalog=TestDB;integrated security=True;MultipleActiveResultSets=True;";
        var command = "dbo.Procedure";
        var tableAdapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
        tableAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
        var dataSet = new DataSet();
        tableAdapter.Fill(dataSet); 
    
        var t1 = dataSet.Tables[0].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type1
            {
                A = row.Field<int>("A"),
            }).ToList();
    
        var t2 = dataSet.Tables[1].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type2
            {
                B = row.Field<int>("B"),
                C = row.Field<string>("C")
            }).ToList();
    
        var t3 = dataSet.Tables[1].Rows.Cast<DataRow>()
            .ToList().Select(row => new Type3
            {
                D = row.Field<int>("D"),
                E = row.Field<string>("E"),
                F = row.Field<string>("F")
            }).ToList();
    
        var result = new ResultModel() { List1 = t1, List2 = t2, List3 = t3 };
    
        return result;
    }
    
    • 我们有一个干净简单的
      ResultModel
    • 使用
      SqlDataAdapter
      DataSet
      可以轻松读取多个结果
    • 使用
      Cast()
      使我们能够对
      DataTable.Rows使用
      Linq
    • 使用
      字段(“字段”)
      可以获得字段的键入值

      • 在这种情况下,我认为最好保持简单

      • 您有一个返回3个结果集的存储过程,因此创建一个包含这3个结果集的模型
      • 要填充
        ResultModel
        ,最好使用
        SqlDataAdapter
        DataSet
        。它使事情变得非常简单,非常简单