【问题标题】:looking for suggesions re: accessing data and populating List/arraylist/list寻找建议:访问数据并填充 List/arraylist/list
【发布时间】:2009-06-03 01:38:14
【问题描述】:

我想做这样的事情:

  1. 使用数据读取器访问数据库中的记录。我不知道会返回多少条记录——大部分时间在 1 到 300 条之间。每条记录的数据将类似于“0023”、“Eric”、“Harvest Circle”、“Boston”。
  2. 我想立即填充某些内容(数组、列表?)并关闭连接。
  3. 将填充的对象传回我的 Web 服务,我会将其转换为 JSON,然后再发送给客户端。

我遇到的问题是使用数据读取器中的数据填充哪些对象/对象。我开始使用 ArrayList(现在已经阅读了有关使用 List 的信息),但是虽然我可以取回所有记录(在本例中只有 2 个项目),但我无法访问每个项目中的各个字段(埃里克,波士顿,等)。

进入计划B:在datareader中foreach记录,将各个列的值添加到数组中,然后将每个数组添加到列表中。我认为这会起作用,但是当我不知道需要实例化多少个数组时,我不确定如何实例化一个数组。换句话说,我通常会这样做 string[] myarray = new string[]{"eric", "boston", "etc"};

但如果我有多个记录,那会是什么样子?填充数组,添加到List,清除原始数组然后重新填充,添加到List等?

任何帮助将不胜感激!另外,我非常愿意接受其他方法。

谢谢!

【问题讨论】:

    标签: c# arrays list sqldatareader


    【解决方案1】:

    这里的标准答案是不使用像实体框架这样的持久层,而是使用您需要的字段创建“实体”类。比如:

    class Customer
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    

    ...然后将它们收集到某种集合中。 List<Customer> 很好。

    List<Customer> customers = new List<Customer>();
    
    string connectionString = null;
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        SqlCommand command = new SqlCommand("GetData");
        using (IDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                Customer c = new Customer();
                c.Id = (int)reader["ID"];
                c.FirstName = (string)reader["FirstName"];
                c.LastName = (string)reader["LastName"];
                customers.Add(c);
            }
        }
    }
    

    如果您有大量表或可变字段列表,则可能难以维护。不过,对于简单的任务,这很好用。

    【讨论】:

    • 谢谢 - 我认为我不必创建一个类来存储值,但似乎这是要走的路!
    【解决方案2】:

    您可能不需要像 List 或数组这样的具体类。 IEnumerable 可能已经足够好了。考虑到这一点,这是我最喜欢的模式:

    public IEnumerable<IDataRecord> GetData()
    {
        using (var cn = getOpenConnection(connectionString))
        using (var cmd = new SqlCommand("GetData", cn))   
        using (var rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {
                yield return (IDataRecord)rdr;
            }
        }
    }
    

    您也可以对其进行修改以创建强类型业务对象,但我通常将其保存在单独的层/层中。迭代器块将进行延迟评估/延迟执行,因此额外的翻译层不会需要对结果进行额外的迭代。

    这段代码有一个技巧。您需要确保在某个时间点将每条记录中的数据复制到真实对象。你不能直接绑定到它,否则你会得到可能令人惊讶的结果。我更经常使用的一种变体是使该方法具有通用性,并需要一个Func&lt;IDataRecord, T&gt; 参数来在读取每条记录时对其进行翻译。

    【讨论】:

    • 我从未考虑过保留从 DataReader 返回的 IDataRecords。我必须记住这一点......
    • 我对此知之甚少,无法将其作为公认的答案,但我一定会试一试。谢谢,乔尔!
    • @Michael Petrotta:它的美妙之处在于它不会“保留”任何东西。一次只有一个项目在内存中。权衡可能会使您的数据库连接保持更长时间。
    • 这段代码非常“干净”和整洁。我喜欢它:) ...正是我想要的。谢谢乔尔。
    【解决方案3】:

    迈克尔的回答通常是您最好的选择。一旦事情开始变得复杂,您就可以添加抽象(您需要包含 sql 阅读器和各种其他有趣事物的对象工厂)并开始传递对象和工厂。我发现这种策略非常有用,并且可以在您的数据库相关项目中使用编写良好的数据层类。

    另一种方法是使用SqlDataAdapter 并将您的输出转换为DataSet。以我的经验,这非常笨拙,通常是一个非常糟糕的主意。也就是说,如果您倾向于获取一大块数据并对其进行操作(更新片段、添加新片段、删除片段),这可能是使用 C# 代码在内存中执行此操作的好方法。在尝试这种技术之前三思而后行。这基本上相当于抓取数据并填充行列表,尽管 DataSet 比数组包含更多内容(例如,它包含列名)。

    我觉得使用SqlDataAdapter 来填充DataSet 是最接近您在问题中所要求的答案,但就为您提供实际需要而言是最差的答案。

    【讨论】:

    • 谢谢,布赖恩。我过去广泛使用过类型化数据集(我的 .net 目前超级生锈)。由于我希望使用高级别的,我试图避免数据集的开销,除了插入/更新/删除。所有选择都将使用数据读取器来提高速度。
    【解决方案4】:

    创建一个对象,该对象的属性与将在数据读取器中返回的字段相匹配:

    public class MyClass
    {
       public int Id{get;set;}
       public string Name{get;set;}
       ....
    }
    

    然后,遍历数据读取器中的所有结果。然后,创建此类型的对象并使用该记录的列中的值设置所有属性。然后,将它们添加到 List

    【讨论】:

      【解决方案5】:

      我建议研究 LINQ to SQL(如果您有一个非常简单的数据库)或 NHibernate(如果您有一个更复杂的数据库)。这些是 OR 映射器,可以大大简化将 SQL 查询转换为可在您的域中使用、通过服务等传递的对象的过程。

      【讨论】:

        【解决方案6】:

        我认为这里有一个简单的解决方案。我会创建一个 DataAdapter,然后用数据填充一个 DataTable。然后您可以关闭连接,数据表将保持填充状态,因为与 ADO 不同,ADO.NET 默认为断开连接的记录集。

        然后您可以通过字段名轻松访问数据,例如,

        myDataTable["FirstName"].ToString()
        

        如果您要做的只是将数据转换为 JSON,那么创建一个将属性映射到数据库字段的对象似乎是不必要的,因为 ADO.NET 为您提供了开箱即用的功能。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-28
          • 2019-11-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多