寻找建议:访问数据并填充List / arraylist / list

时间:2009-06-03 01:38:14

标签: c# arrays list sqldatareader

我希望做这样的事情:

  1. 使用datareader访问db中的记录。我不知道有多少记录会回来 - 大部分时间介于1到300之间。每条记录的数据看起来都像“0023”,“Eric”,“Harvest Circle”,“Boston”。
  2. 我想立即填充某些内容(数组,列表?)并关闭连接。
  3. 将填好的对象传回我的网络服务,然后将其转换为JSON,然后再发送给客户端。
  4. 我遇到的问题是用datareader填充数据的对象/对象。我开始使用ArrayList(现在已经阅读了有关使用List的内容),但是虽然我可以取回所有记录(在这种情况下只有2个项目),但我无法访问每个项目中的各个字段(Eric,Boston,等)。

    在datareader中输入Plan B:foreach记录,将各列值添加到数组中,然后将每个数组添加到List中。我认为这会有效,但我不知道如何在不知道需要实例化多少数组的情况下实例化数组。换句话说,我通常会做这个字符串[] myarray = new string [] {“eric”,“boston”,“etc”};

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

    任何帮助将不胜感激!此外,我对采取其他方式非常开放。

    谢谢!

6 个答案:

答案 0 :(得分:5)

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

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);
        }
    }
}

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

答案 1 :(得分:3)

你可能不需要像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<IDataRecord, T>参数来翻译每个记录。

答案 2 :(得分:1)

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

另一种方法是使用SqlDataAdapter并将输出转换为DataSet。根据我的经验,这是非常笨拙的,通常是一个非常糟糕的主意。也就是说,如果你倾向于抓取一大块数据,操纵它(更新碎片,添加新碎片,删除碎片),这可能是用C#代码在内存中完成它的好方法。在尝试这种技术之前要三思。这基本上等同于抓取数据并填充行列表,尽管DataSet中的内容比数组多一些(例如它包含列名)。

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

答案 3 :(得分:0)

创建一个对象,该对象的属性与将在datareader中返回的字段相匹配:

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

然后,预测datareader中的所有结果。然后,创建此类型的对象,并使用该记录的列中的值设置所有属性。然后,将它们添加到List&lt; MyClass&gt;。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

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

myDataTable["FirstName"].ToString()

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