朧の.Netの足跡
問合せ先:support@oborodukiyo.info サイト内検索はこちら 
.Net DataRelationでデータを絞り込む





このサンプルコードは、DataRelationを使って3つのコンボボックスを順に絞り込んでいく方法です。
データベースはSQLServerについてるAdventureWorksを使用しています。
メリットとしてはデータをすべて取り込んだ後のコンボボックスのデータの内容のスピードは速いと思お居ます。
デメリットとしてはテーブルデータをすべて取り込むのでメモリを大きく必要とするのと、必要のないデータも取得するのでネットワークトラフィックが増えたり、最初のロードの時間がかかってしまうことです。

C#

public partial class Form1 : Form
{
    DataSet ds = new DataSet();
    
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        //SQL Serverへの接続情報用変数
        SqlConnectionStringBuilder connBldr = new SqlConnectionStringBuilder();
        //ここではローカルのSQL Serverを指定しています。
        connBldr.DataSource = @".\SQLEXPRESS";
        //AdventureWorksを使用します。
        connBldr.InitialCatalog = "AdventureWorks";
        //Windowsアカウント情報を利用します。
        connBldr.IntegratedSecurity = true;
        //SQL Serverへの接続用変数
        SqlConnection conn = new SqlConnection(connBldr.ConnectionString);
        //SQLコマンド用変数
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = conn;
        //ComboBox1用のSQL
        cmd.CommandText = "SELECT CustomerID FROM Sales.Customer ORDER BY CustomerID";
        SqlDataAdapter ad = new SqlDataAdapter();
        ad.SelectCommand = cmd;
        ds.Tables.Add("Customer");
        ad.Fill(ds.Tables["Customer"]);
        //ComboBox2用のSQL
        cmd.CommandText = "SELECT CustomerID,SalesOrderID FROM Sales.SalesOrderHeader "
            + "ORDER BY CustomerID,SalesOrderID";
        ds.Tables.Add("SalesOrderHeader");
        ad.Fill(ds.Tables["SalesOrderHeader"]);
        //ComboBox2用のSQL
        cmd.CommandText = "SELECT SalesOrderID,SalesOrderDetailID FROM Sales.SalesOrderDetail "
            + "ORDER BY SalesOrderID,SalesOrderDetailID";
        ds.Tables.Add("SalesOrderDetail");
        ad.Fill(ds.Tables["SalesOrderDetail"]);
        
        this.comboBox1.DisplayMember = "CustomerID";
        this.comboBox1.ValueMember = "CustomerID";
        //DisplyaMemberやValueMemberを設定してからDataSourceを設定する
        this.comboBox1.DataSource = ds.Tables[0];
        //ComboBox2のDataSourceは、ComboBox1が選択された時に設定する
        this.comboBox2.DisplayMember = "SalesOrderID";
        this.comboBox2.ValueMember = "SalesOrderID";
        //ComboBox3のDataSourceは、ComboBox2が選択された時に設定する
        this.comboBox3.DisplayMember = "SalesOrderDetailID";
        this.comboBox3.ValueMember = "SalesOrderDetailID";
        //ここでDataRelationを設定することによって、絞り込み処理を簡単にできるようになる。
        ds.Relations.Add(new DataRelation("Customer", ds.Tables[0].Columns["CustomerID"], ds.Tables[1].Columns["CustomerID"]));
        ds.Relations.Add(new DataRelation("SalesOrder", ds.Tables[1].Columns["SalesOrderID"], ds.Tables[2].Columns["SalesOrderID"]));
    }
    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        //項目が選択されており、かつ有効な値かどうかチェックする
        if (comboBox1.SelectedIndex > -1 && comboBox1.SelectedValue.ToString() != "")
        {
            //ComboBox1で選択された値にマッチする行を抽出
            DataRow[] drs = ds.Tables[0].Select("CustomerID = " + comboBox1.SelectedValue);
            //マッチするものが有ったかチェック
            if (drs.Length > 0)
            {
                foreach (DataRow dr in drs)
                {
                    //DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出
                    DataRow[] drs2 = dr.GetChildRows("Customer");
                    //マッチする行があったかチェック
                    if (drs2.Length > 0)
                    {
                        //ComboBox2を有効にしてデータソースを設定する
                        comboBox2.Enabled = true;
                        comboBox2.DataSource = drs2.CopyToDataTable();
                    }
                    else
                    {
                        comboBox2.SelectedIndex = -1;
                        comboBox2.Enabled = false;
                        comboBox3.SelectedIndex = -1;
                        comboBox3.Enabled = false;
                    }
                }
            }
        }
    }
    private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
    {
        //項目が選択されており、かつ有効な値かどうかチェックする
        if (comboBox2.SelectedIndex > -1 && comboBox2.SelectedValue.ToString() != "")
        {
            //ComboBox2で選択された値にマッチする行を抽出
            DataRow[] drs = ds.Tables[1].Select("SalesOrderID = " + comboBox2.SelectedValue);
            //マッチするものが有ったかチェック
            if (drs.Length > 0)
            {
                foreach (DataRow dr in drs)
                {
                    //DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出
                    DataRow[] drs2 = dr.GetChildRows("SalesOrder");
                    //マッチする行があったかチェック
                    if (drs2.Length > 0)
                    {
                        //ComboBox3を有効にしてデータソースを設定する
                        comboBox3.Enabled = true;
                        comboBox3.DataSource = drs2.CopyToDataTable();
                    }
                    else
                    {
                        comboBox3.SelectedIndex = -1;
                        comboBox3.Enabled = false;
                    }
                }
            }
        }
    }
}

VB.NET

Imports System.Data.SqlClient
Imports System.Data
Public Class Form1
    Dim ds As DataSet = New DataSet()
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'SQL Serverへの接続情報用変数
        Dim connBldr As SqlConnectionStringBuilder = New SqlConnectionStringBuilder()
        'ここではローカルのSQL Serverを指定しています。
        connBldr.DataSource = "."
        'AdventureWorksを使用します。
        connBldr.InitialCatalog = "AdventureWorks"
        'Windowsアカウント情報を利用します。
        connBldr.IntegratedSecurity = True
        'SQL Serverへの接続用変数
        Dim conn As SqlConnection = New SqlConnection(connBldr.ConnectionString)
        'SQLコマンド用変数
        Dim cmd As SqlCommand = New SqlCommand()
        cmd.Connection = conn
        'ComboBox1用のSQL
        cmd.CommandText = "SELECT CustomerID FROM Sales.Customer ORDER BY CustomerID"
        Dim ad As SqlDataAdapter = New SqlDataAdapter()
        ad.SelectCommand = cmd
        ds.Tables.Add("Customer")
        ad.Fill(ds.Tables("Customer"))
        'ComboBox2用のSQL
        cmd.CommandText = "SELECT CustomerID,SalesOrderID FROM Sales.SalesOrderHeader ORDER BY CustomerID,SalesOrderID"
        ds.Tables.Add("SalesOrderHeader")
        ad.Fill(ds.Tables("SalesOrderHeader"))
        'ComboBox3用のSQL
        cmd.CommandText = "SELECT SalesOrderID,SalesOrderDetailID FROM Sales.SalesOrderDetail ORDER BY SalesOrderID,SalesOrderDetailID"
        ds.Tables.Add("SalesOrderDetail")
        ad.Fill(ds.Tables("SalesOrderDetail"))
        Me.ComboBox1.DisplayMember = "CustomerID"
        Me.ComboBox1.ValueMember = "CustomerID"
        'DisplyaMemberやValueMemberを設定してからDataSourceを設定する
        Me.ComboBox1.DataSource = ds.Tables(0)
        'ComboBox2のDataSourceは、ComboBox1が選択された時に設定する
        Me.ComboBox2.DisplayMember = "SalesOrderID"
        Me.ComboBox2.ValueMember = "SalesOrderID"
        'ComboBox3のDataSourceは、ComboBox2が選択された時に設定する
        Me.ComboBox3.DisplayMember = "SalesOrderDetailID"
        Me.ComboBox3.ValueMember = "SalesOrderDetailID"
        'ここでDataRelationを設定することによって、絞り込み処理を簡単にできるようになる。
        ds.Relations.Add(New DataRelation("Customer", ds.Tables(0).Columns("CustomerID"), ds.Tables(1).Columns("CustomerID")))
        ds.Relations.Add(New DataRelation("SalesOrder", ds.Tables(1).Columns("SalesOrderID"), ds.Tables(2).Columns("SalesOrderID")))
    End Sub
    Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        '項目が選択されており、かつ有効な値かどうかチェックする
        If ComboBox1.SelectedIndex > -1 And Not ComboBox1.SelectedValue.ToString() = "" Then
            'ComboBox1で選択された値にマッチする行を抽出
            Dim drs() As DataRow = ds.Tables(0).Select("CustomerID = " & ComboBox1.SelectedValue.ToString())
            'マッチするものが有ったかチェック
            If drs.Length > 0 Then
                For Each dr As DataRow In drs
                    'DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出
                    Dim drs2() As DataRow = dr.GetChildRows("Customer")
                    'マッチする行があったかチェック
                    If drs2.Length > 0 Then
                        'ComboBox2を有効にしてデータソースを設定する
                        ComboBox2.Enabled = True
                        ComboBox2.DataSource = drs2.CopyToDataTable()
                    Else
                        ComboBox2.SelectedIndex = -1
                        ComboBox2.Enabled = False
                        ComboBox3.SelectedIndex = -1
                        ComboBox3.Enabled = False
                    End If
                Next
            End If
        End If
    End Sub
    Private Sub ComboBox2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox2.SelectedIndexChanged
        '項目が選択されており、かつ有効な値かどうかチェックする
        If ComboBox2.SelectedIndex > -1 And Not ComboBox2.SelectedValue.ToString() = "" Then
            'ComboBox2で選択された値にマッチする行を抽出
            Dim drs() As DataRow = ds.Tables(1).Select("SalesOrderID = " & ComboBox2.SelectedValue.ToString())
            'マッチするものが有ったかチェック
            If drs.Length > 0 Then
                For Each dr As DataRow In drs
                    'DataRelationを利用するGetChildRowsメソッドを使って子テーブルから行を抽出
                    Dim drs2() As DataRow = dr.GetChildRows("SalesOrder")
                    'マッチする行があったかチェック
                    If drs2.Length > 0 Then
                        'ComboBox3を有効にしてデータソースを設定する
                        ComboBox3.Enabled = True
                        ComboBox3.DataSource = drs2.CopyToDataTable()
                    Else
                        ComboBox3.SelectedIndex = -1
                        ComboBox3.Enabled = False
                    End If
                Next
            End If
        End If
    End Sub
End Class








良いやや良い普通やや悪い悪い
0 0 1 0 0

投稿日時評価コメント