如何在 SqlDataReader 之前知道或获取数组大小?并将其作为 json 返回

Posted

技术标签:

【中文标题】如何在 SqlDataReader 之前知道或获取数组大小?并将其作为 json 返回【英文标题】:How can I know or get the Array Size before a SqlDataReader? and return it as a json 【发布时间】:2014-09-05 19:19:25 【问题描述】:

我想知道我的数组的大小以循环所需的时间,但我不知道如何以有效的方式进行,我能想到的唯一方法是将其放入阅读器并计数,然后使用另一个时间阅读器并插入值:(我是学生

这里是代码

myConnection.Open();
SqlCommand sqlCommand = new SqlCommand(" SELECT * FROM table ", myConnection);

SqlDataReader dr = sqlCommand.ExecuteReader();

Calendar[] loArrayRegistrosCalendario = new Calendar[200]; //200 As an example

if (dr != null)

    int i = 0;

    while (dr.Read())
    
        Calendar loRegistroDia = new Calendar();
        loRegistroDia.User = (dr["user"].ToString());

        loArrayRegistrosCalendario[i] = loRegistroDia;
        i = i + 1;
    


return loArrayRegistrosCalendario;

【问题讨论】:

为什么不使用支持动态项目数的类(如List<>()),然后如果你使用数组你可以调用.ToArray() 我已经用 list 做了,但我需要一个 json 对象,这就是我创建一个类的原因:C 您可以像数组一样轻松地将 List 序列化为 JSON 数组。 真的吗? D: 我已经调查了 3 个小时才知道我需要开设一个课程并这样做,因为我必须对其进行序列化:s Here is an example where I've serialize both a list and an array, they are exactly the same。请注意,您的问题一个不好的问题,因为它是在最近的编辑之前,XY Problem。 【参考方案1】:

你根本不需要数组。

myConnection.Open();

var loArrayRegistrosCalendario = new List<Calendar>();

using (SqlCommand sqlCommand = new SqlCommand(" SELECT * FROM table ", 
  myConnection);)


  using (SqlDataReader dr = sqlCommand.ExecuteReader())
  

    if (dr != null)
    
      while (dr.Read())
      
        Calendar loRegistroDia = new Calendar();
        loRegistroDia.User = (dr["user"].ToString());

        loArrayRegistrosCalendario.Add(loRegistroDia);
      
    
  


return loArrayRegistrosCalendario;

(附带说明,请正确处理 IDisposable 对象,例如应正确处理 SqlCommand 和 SqlDataReader。我建议对两者都使用 using() 语句。)

序列化日历数组和日历列表将产生相同的结果: DotNetFiddle Example.

public class Program

    public static void Main()
    
        var myobject = new MyObject();
        myobject.Calendars1 = new List<Calendar>();
        for (DateTime dt = new DateTime(1980,1,1); dt <= new DateTime(1981,1,1); dt = dt.AddMonths(1))
        
            myobject.Calendars1.Add(new Calendar()  Name =  dt.ToString("MMMM") );
        
        
        myobject.Calendars2 = myobject.Calendars1.ToArray();
        
        var json1 = JsonConvert.SerializeObject(myobject.Calendars1);
        var json2 = JsonConvert.SerializeObject(myobject.Calendars2);
        
        Console.WriteLine(json1);
        Console.WriteLine(json2);
    


public class MyObject

    public List<Calendar> Calendars1  get; set; 
    public Calendar[] Calendars2  get; set; 


public class Calendar

    public string Name  get; set; 

结果:

["姓名":"一月","姓名":"二月","姓名":"三月","姓名":"四月","姓名":"五月","姓名":"六月","姓名":"七月","姓名":"八月","姓名":"九月","姓名":"十月","姓名":"十一月","姓名":"十二月","姓名":"一月"]

["姓名":"一月","姓名":"二月","姓名":"三月","姓名":"四月","姓名":"五月","姓名":"六月","姓名":"七月","姓名":"八月","姓名":"九月","姓名":"十月","姓名":"十一月","姓名":"十二月","姓名":"一月"]

【讨论】:

List&lt;Calendar[200]&gt; 数组列表?这是你真正想要的吗? @AaronLS 绝对! :) 谢谢。 @Erik Philips 真棒、高效、完整且漂亮的答案!非常感谢:)【参考方案2】:

只需创建一个 SQL 命令来获取计数,如下所示:

SqlCommand sqlCommand = new SqlCommand(" SELECT Count (*) FROM table ", myConnection);

int rows = sqlCommand.ExecuteScalar();

Calendar[] loArrayRegistrosCalendario = new Calendar[rows];

【讨论】:

我对这里的反对票感到困惑。如果他根据数据集的大小创建他的数组,那么它肯定只会循环正确的项目数......还是我在这里遗漏了什么? 也许是因为这增加了对数据库的另一个调用。另外,如果在获取计数和选择行之间从表中添加或删除行怎么办? 我部分同意你的第一点,尽管我认为在这个例子中开销是最小的。但是,我看不到行的添加/删除是一个问题,除非它发生在打开阅读器和获取计数之间的瞬间。 根据我的经验,在一瞬间发生的事情比人们想象的要频繁得多。竞态条件可能很难追踪,最好尽可能避免产生竞态条件。

以上是关于如何在 SqlDataReader 之前知道或获取数组大小?并将其作为 json 返回的主要内容,如果未能解决你的问题,请参考以下文章

如何从 SqlDataReader 获取列的表名

如何在 C# 中使用 SqlDataReader 获取行数

如何从 SqlDataReader 中只获取一些行?

如何使用 SqlDataReader 获取位值并将其转换为布尔值?

如何从 SqlDataReader 获取 int32 和字符串。收到错误 System.IndexOutOfRangeException: 'StudentID'

如果在 SqlDataReader 之前关闭 SqlConnection 会发生啥?