2017-03-24 6 views
2

データベースに接続するMySQLローカルデータベースを使用していますが、これは問題になりません。私は約6つの異なるテーブルを持つ小規模のデータベースを持っており、それぞれが約4-6列、行は< 100です(大きなデータでは動作しません)。ローカルMySQLデータベースからSELECTクエリの結果を返すジェネリック関数 - C#.Net 4.6.1

これらのデータベースからデータを選択する必要があるWPFアプリケーションを作成していますが、追加する必要はありません。データベースには静的データが格納されています。静的データはSELECT文を実行し、その結果を使用してWPFアプリケーションに表示する必要があります。

DBHandlerクラスで関数を作成する必要があります。このクラスは、システムの他のクラスから呼び出すことができ、指定したSELECTステートメントでデータベースを照会し、結果を使用することができます。問題は私のクエリが変わることです。時には、私はある列を要求しているかもしれません。

(SELECT id FROM students WHERE name = 'Conor') 

時々私はこのような、より複雑な文で...(擬似)の複数の行のために呼び出すことがあります

(SELECT name, address FROM destinations WHERE long, lat intersects_with (SELECT long, lat FROM trains)) 

私は常に期待され、クエリでこの関数を呼び出すたびにデータレスポンスの形式なので、リスト<>または配列を返すだけであれば、その関数が一般的であり、1つのクエリまたはテーブルに固有ではないにもかかわらず、データへのアクセスに問題はありません。

は、これまでのところ、私はこれを試してみました:

public static MySqlDataReader Query(string SQLQuery) 
    { 
     using (MySqlConnection con = new MySqlConnection(connectionString)) 
     { 
      con.Open(); 

      MySqlCommand command = new MySqlCommand(SQLQuery, con); 

      MySqlDataReader reader = command.ExecuteReader(); 

      return reader; 
     } 
    } 

    // Some other class 
    MySqlDataReader reader = DBHandler.Query("SELECT * FROM destinations"); 

    while (reader.Read()) 
    { 
     MessageBox.Show(reader[0].ToString()); 
    } 

これは動作しません、それは読者が閉じて文句を言うので。私は単純にMySqlDataReaderオブジェクトを返すことはできないと推測します。

私の次の考え方は、実際のクエリを行い、このクエリ関数内のすべてのデータを返し、返されるすべての結果を格納することです。しかし、どのように私は可変SELECTクエリのために一般的である必要があるので、データを返す行または列の数の固定サイズを持つことができないので、私の主な問題です。リスト<>またはリスト<>の中のリスト<>に保存できると思っていましたが、どのようにレイアウトするかは分かりません。

これはたくさん聞いていますが、私の心を揺るがしています。この一般的なSELECT機能をどうやって作るのか分かりませんが、必要な時にいつでも呼び出す必要があるので、システムの別の部分でデータを取得します。

ありがとうございました!

答えて

1

を閉じているので、あなたは、(接続を使用して)内のループに必要な、オンラインになっています。したがって、あなたのコードがusingブロックを終了すると、接続は読者と同様に閉じられます。ただし、Queryメソッドには、MySqlDataReaderを受け取るAction delegateを渡すことができます。この関数は、Queryの呼び出し側によって定義されるため、データベースをオープンし、照会し、読み取るために使用される定型コードへの一般的なアプローチを維持しながら、異なる表に対してそれをカスタマイズできます。発信者コードで

public static MySqlDataReader Query(string SQLQuery, Action<MySqlDataReader> loader) 
{ 
    using (MySqlConnection con = new MySqlConnection(connectionString)) 
    { 
     con.Open(); 

     using(MySqlCommand command = new MySqlCommand(SQLQuery, con)) 
     using(MySqlDataReader reader = command.ExecuteReader()) 
     { 
      // here you can pass the reader, you are still inside the using block 
      while(reader.Read()) 
       loader.Invoke(reader) 
     } 
    } 
} 

あなたのコードの異なるポイントでもちろん

List<Destination> destinations = new List<Destination>(); 
MySqlDataReader reader = DBHandler.Query("SELECT * FROM destinations", dataLoaderForDestination); 
Console.WriteLine("Loaded " + destinations.Count + " destinations"); 

private void dataLoaderForDestination(MySqlDataReader reader) 
{ 
    Destination dest = new Destination(); 
    dest.Address = reader.GetString(0); 
    dest.Nation = reader.GetInt32(1); 
    ... 
    destinations.Add(dest); 
} 

を書くことができ、あなたによって返されたデータの異なるセットに合わせたさまざまなアクションデリゲートへの参照を渡すことができますクエリ

List<Student> students = new List<Student>(); 
private void dataLoaderForStudents(MySqlDataReader reader) 
{ 
    Student st = new Student(); 
    st.Name = reader.GetString(0); 
    st.Class = reader.GetInt32(1); 
    students.Add(st); 
} 
+0

ありがとうございます - これは本当に役立つと思います。私は30分後にそれを打ち明けます。しかし、言及したいことの一つは、データベース内のテーブルに対応するプロジェクトのクラスがないことです。たとえば、これらのプロパティを保持するStudentクラスやDestinationクラスはありません。私は単純にデータにアクセスし、その結果を一度だけ使用します。私はまだあなたのメソッドを使用することができますが、私はSQLクエリを使用してデータを分析するたびに関数を作成します。 – Conor

+1

各テーブルのクラスを作成することをお勧めします。あなたの人生はずっと楽になります。 (どんな場合でも 'List 'アプローチを使用したい場合は、そのTが何であるかを明確にする必要があります) – Steve

+1

これからやります。実際、リスト、リストなどのリストにすべての情報を格納するのはデータベース全体ではなく、少量のデータと静的なものであるため、追加や削除は必要ありません。私はリストをループして関係を探すことができます。たぶん、これは実際には良いアイデアですか?申し訳ありませんが、そのような種類の寛大な知識とアドバイスは、おそらく他の誰かがそれを使用します。 – Conor

0

読者はあなたが使用してのままにしておくと、connctionが配置され、あなたは、その接続がクローズされたときにDataReaderを使用しようとすることはできません

+0

私は読者が行く方法ではありません、私はあなたの応答を感謝しますが、大きな画像で多くの助けを私に提供しません。 「内部で(接続を使用して)」ループを使用するとどうなりますか?また、これらの値を関数からどのように返すのですか?一般的に応答の可変形式を返すために使用できますか? – Conor

関連する問題