2

我想做这样的事情:

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

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

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

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

任何帮助将不胜感激!此外,我对这样做的其他方法持开放态度。

谢谢!

4

6 回答 6

5

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

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

...然后将这些收集到某种集合中。AList<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);
        }
    }
}

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

于 2009-06-03T01:43:13.650 回答
3

奇怪的是,您不需要像 aList或数组这样的具体类。一个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>参数来在读取每条记录时对其进行翻译。

于 2009-06-03T02:32:48.123 回答
1

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

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

我觉得使用 anSqlDataAdapter来填充 aDataSet是最接近于给你在你的问题中要求的答案,但在给你真正需要的方面是最糟糕的答案。

于 2009-06-03T02:07:57.267 回答
0

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

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

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

于 2009-06-03T01:43:47.580 回答
0

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

于 2009-06-03T02:00:45.847 回答
0

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

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

myDataTable["FirstName"].ToString()

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

于 2009-06-03T02:15:47.953 回答