2

私はこのようなことをしようとしています:

  1. データリーダーを使用して db のレコードにアクセスします。どのくらいのレコードが戻ってくるかはわかりません - ほとんどの場合、1 から 300 の間のどこかです。データは、各レコードの「0023」、「Eric」、「Harvest Circle」、「Boston」のようになります。
  2. すぐに何か (配列、リスト?) を入力して、接続を閉じたいと思いました。
  3. 入力されたオブジェクトを Web サービスに戻し、クライアントに送信する前に JSON に変換します。

私が直面している問題は、データリーダーからのデータをどのオブジェクトに入力するかです。最初は ArrayList を使用していましたが (代わりに List を使用する方法について読みました)、すべてのレコード (この場合は 2 つのアイテムのみ) を取得できましたが、各アイテム内の個々のフィールド (Eric、Boston、等)。

プラン B: foreach レコードを datareader に入力し、個々の列の値を配列に追加してから、各配列をリストに追加します。これはうまくいくと思いますが、インスタンス化する必要がある配列の数がわからない場合、配列をインスタンス化する方法がわかりません。言い換えれば、私は通常、この string[] myarray = new string[]{"eric", "boston", "etc"}; を実行します。

しかし、複数のレコードがある場合、それはどのように見えるでしょうか? 配列を作成し、リストに追加し、元の配列をクリアしてから再作成し、リストに追加しますか?

どんな助けでも大歓迎です!また、私はこれを行う別の方法に対して非常にオープンです。

ありがとう!

4

6 に答える 6

5

ここでの標準的な答えは、Entity Framework のような永続化レイヤーを使用しない限り、必要なフィールドを持つ「エンティティ」クラスを作成することです。何かのようなもの:

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

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

それを変更して、厳密に型指定されたビジネス オブジェクトを作成することもできますが、私は通常、それを別のレイヤー/層に保持します。Iterator ブロックは遅延評価/遅延実行を行うため、追加の翻訳層は結果の追加の反復を必要としません。

このコードには 1 つのトリックがあります。ある時点で、各レコードのデータを実際のオブジェクトに確実にコピーする必要があります。それに直接バインドすることはできません。そうしないと、驚くべき結果が得られる可能性があります。私がより頻繁に使用するバリエーションの 1 つは、メソッドをジェネリックにし、Func<IDataRecord, T>各レコードが読み取られるときに変換するための引数を要求することです。

于 2009-06-03T02:32:48.123 に答える
1

マイケルの答えは、通常、最善の策です。物事が複雑になり始めたら、抽象化を追加して (SQL リーダーやその他のさまざまな楽しいものを取り込むオブジェクト ファクトリが必要になります)、オブジェクトとファクトリを渡し始めることができます。この戦略は非常に役に立ち、適切に作成されたデータ層クラスはデータベース関連のプロジェクト全体で使用できることがわかりました。

1 つの代替方法は、SqlDataAdapterand を使用して、出力を に変換することDataSetです。私の経験では、これはかなり扱いにくく、一般的にかなり悪い考えです。とはいえ、データのチャンクを取得して操作する (断片を更新する、新しい断片を追加する、断片を削除する) 傾向がある場合、これは C# コードを使用してメモリ内で行うのに適した方法です。このテクニックを試す前によく考えてください。これは基本的に、データを取得して行のリストに入力することと同じですがDataSet、配列よりも少し多くのものがあります (たとえば、列名が含まれます)。

を使用しSqlDataAdapterて a に入力するDataSetことは、質問で求めているものを提供するための最も近い答えですが、実際に必要なものを提供するという点では最悪の答えだと思います。

于 2009-06-03T02:07:57.267 に答える
0

datareader に返されるフィールドに一致するプロパティを持つオブジェクトを作成します。

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

次に、データリーダーのすべての結果に対して foreach を実行します。次に、このタイプのオブジェクトを作成し、そのレコードの列の値を使用してすべてのプロパティを設定します。次に、それらを List<MyClass> に追加します。

于 2009-06-03T01:43:47.580 に答える
0

LINQ to SQL (非常に単純なデータベースの場合) または NHibernate (より複雑なデータベースの場合) を検討することをお勧めします。これらは、SQL クエリをドメイン内で使用できるオブジェクトに変換するプロセスを大幅に簡素化できる OR マッパーであり、サービスを介して渡すことができます。

于 2009-06-03T02:00:45.847 に答える
0

ここでは簡単な解決策が適切だと思います。DataAdapter を作成してから、DataTable にデータを入力します。ADO とは異なり、ADO.NET は既定で切断されたレコードセットを使用するため、接続を閉じることができます。データ テーブルには値が設定されたままになります。

次に、フィールド名でデータに簡単にアクセスできます。

myDataTable["FirstName"].ToString()

データを JSON に変換するだけの場合、プロパティをデータベース フィールドにマップするオブジェクトを作成する必要はないように思われます。

于 2009-06-03T02:15:47.953 に答える