Handling Multi-Table DataSet Object with Relationship

C# DataSet: इस पुस्तक में अभी तक हमने जितने भी Example Programs Create किए हैं, वे सभी पूरी तरह से केवल एक Single Table के Data पर ही आधारित रहे हैं। जबकि हम सभी जानते हैं कि Professional Development में हमेंशा एक से ज्यादा Tables के Data आपस में मिलकर Final Results Generate करते हैं और ADO.NET dk DataSet Object भी हमें यही सुविधा Provide करता है। DataSet Object में हम Multiple DataTable Objects को Contain कर सकते हैं, जो कि Underlying Database की एक से अधिक Physical Tables को In-Memory Represent करने में सक्षम होता है।

इस स्थिति में हम हमारे DataSet के DataRelation Collection का प्रयोग करते हुए अपने DataSet में Contained विभिन्न DataTables के बीच Relationships को भी Establish कर सकते हैं और अपने Disconnected DataSet Object की विभिन्न DataTables को ठीक इस प्रकार से Access व Manipulate कर सकते हैं, जैसे कि वे सभी वास्तव में Connected Mode में Exist हों।

हालांकि Multiple Tables से सम्बंधित हमारे इस उदाहरण में हम हमारे सभी Codes मुख्‍य Windows Forms Application में ही लिख रहे हैं लेकिन Professional Development के दौरान हमें अपने Business Logics व User Interface Logics को Mix नहीं करना चाहिए, बल्कि एक Library File Create करके अपने Application से सम्बंधित सभी Business Logics को उस Library में User Interface Logics से अलग रखना चाहिए।

Multiple Tables को Handle करने से सम्बंधित हमारे इस उदाहरण में सबसे पहले हमें एक नया Windows Forms Application Project Create करना होता है और अपने Form को निम्न चित्रानुसार Design करना होता है, जिस पर चार DataGridView Controls (dgvProducts, dgvCustomers, dgvOrders, dgvOrderDetails) Northwind Database की चार अलग Tables (Products, Customers, Orders, Order Details) के Data को Represent कर रहे हैं।

साथ ही इसी Form पर btnUpdate नाम का एक Button भी Placed है, जिसे Click करने पर Execute होने वाला Click Event Handler, चारों DataGridView Controls के Data को DataAdapter Object के माध्‍यम से Underlying Database की Physical Tables में Permanently Update करने का काम करता हैं।

Multi-Table C# DataSet Object with Relationship - Hindi

Configuring DataAdapter Objects

Form Design करने के बाद सबसे पहला काम यही होता है कि हम DataAdapter Objects को Configure करें, क्योंकि यही वह Object होता है, जो Underlying Database का Interaction Application के Disconnected Objects से करवाता है।

अपने Application Program को छोटा बनाए रखने के लिए इस Program में भी हम CommandBuilder Object को Use कर रहे हैं जो कि Data Adapter Object के लिए जरूरी SQL Commands को Automatically Generate करता है। इस Program में हम तीन DataAdapter Objects Create कर रहे हैं, क्योंकि इस Form पर तीन Tables के Data के साथ Interaction किया जा रहा है। DataAdapter Related विभिन्न जरूरी Configuration करने के लिए हमें हमारे Form की Class को निम्नानुसार Code द्वारा Modify करना होता है:

    public partial class frmMultipleTables : Form
    {
        // Form-wide DataSet.
        private DataSet dsNW = new DataSet("Northwind");

        // Make use of command builders to simplify data adapter configuration.
        private SqlCommandBuilder sqlCBProducts;
        private SqlCommandBuilder sqlCBCustomers;
        private SqlCommandBuilder sqlCBOrders;
        private SqlCommandBuilder sqlCBOrderDetails;

        // Our data adapters (for each table).
        private SqlDataAdapter prodTableAdapter;
        private SqlDataAdapter custTableAdapter;
        private SqlDataAdapter ordersTableAdapter;
        private SqlDataAdapter orderDetailsTableAdapter;

        // Form-wide connection string.
        private string cnStr = string.Empty;

        . . .
    }

जैसाकि इस Code में हम देख सकते हैं कि हमने चार अलग DataAdapter Objects के लिए चार अलग CommandBuilder Objects के Private Fields Create किए हैं, ताकि DataAdapter Objects को आसानी से Configure किया जा सके। जबकि चार अलग Tables के Data को Access व Manipulate करने के लिए हमने चार अलग DataAdapter Objects के Reference Hold करने के लिए Private Fields Create किए है। जबकि पूरे Program के दौरान समान ConnectionString को Use करने के लिए cnStr नाम का एक String Type का Object भी Create किया है।

इस Example में हम ये मान रहे हैं कि ConnectionString को हमने अपने Application के App.config File में ही निम्नानुसार तरीके से Specify कर दिया है, जिसे पूरे Program के दौरान Application द्वारा Use किया जा सकता है:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  
    <connectionStrings>
        <add name="NWSQLProvider" connectionString="Data Source=KULDEEP\SQLSERVEREXPRESS;Initial Catalog=Northwind;Integrated Security=True" 
        />
    </connectionStrings>
</configuration>

जब हम इस प्रकार की App.config File द्वारा अपने Application के लिए Database Connection को Configure करते हैं, तब हमें अपने Application में System.Configuration .dll नाम की Assembly का Reference Add करना होता है। साथ ही अपने Application में System.Configuration Namespace को using Statement के माध्‍यम से Import करना पडता है।

जब हम उपरोक्तानुसार तरीके से App.config File में connectionStrings की Information व System.Configuration Namespace को Specify कर देते हैं, उसके बाद हम हमारे Form के Constructor में इस connectionString को Use करते हुए निम्नानुसार Code लिख सकते हैं:

        public frmMultipleTables()
        {
            InitializeComponent();

            InitializeComponent();
            // Get connection string from *.config file.
            cnStr = ConfigurationManager.ConnectionStrings["NWSQLProvider"].ConnectionString;

            // Create adapters.
            prodTableAdapter = new SqlDataAdapter("Select * from Products", cnStr);
            custTableAdapter = new SqlDataAdapter("Select * from Customers", cnStr);
            ordersTableAdapter = new SqlDataAdapter("Select * from Orders", cnStr);
            orderDetailsTableAdapter = new SqlDataAdapter("Select * FROM [Order Details]", cnStr);
            
            // Auto-generate commands.
            sqlCBProducts = new SqlCommandBuilder(prodTableAdapter);
            sqlCBOrders = new SqlCommandBuilder(ordersTableAdapter);
            sqlCBCustomers = new SqlCommandBuilder(custTableAdapter);
            sqlCBOrderDetails = new SqlCommandBuilder(orderDetailsTableAdapter);

            // Fill tables in DS.
            prodTableAdapter.Fill(dsNW, "Products");
            custTableAdapter.Fill(dsNW, "Customers");
            ordersTableAdapter.Fill(dsNW, "Orders");
            orderDetailsTableAdapter.Fill(dsNW, "Order Details");

            // Build relations between tables.
            BuildTableRelationship();

            // Bind to grids.
            dgvProducts.DataSource = dsNW.Tables["Products"];
            dgvCustomers.DataSource = dsNW.Tables["Customers"];
            dgvOrders.DataSource = dsNW.Tables["Orders"];
            dgvOrderDetails.DataSource = dsNW.Tables["Order Details"];
        }

जब हम हमारे Form को Run करते हैं, तो Form के Create होते ही ये Constructor Code Execute हो जाता है। परिणामस्वरूप सबसे पहले निम्न Code Execute होता है:

// Get connection string from *.config file.
cnStr = ConfigurationManager.ConnectionStrings[“NWSQLProvider”].ConnectionString;

इस Code के Execute होते ही हमारा Application App.config File से ConnectionString को Retrieve करता है और उस ConnectionString को cnStr नाम के String Type के Object में Store कर देता है, जिसे Program के अन्य Parts द्वारा जरूरत के अनुसार उपयोग में लिया जाता है। Connection Establish होने के बाद इस Constructor का निम्न Code Execute होता है:

// Create adapters.
prodTableAdapter = new SqlDataAdapter(“SELECT * FROM Products”, cnStr);
custTableAdapter = new SqlDataAdapter(“SELECT * FROM Customers”, cnStr);
ordersTableAdapter = new SqlDataAdapter(“SELECT * FROM Orders”, cnStr);
orderDetailsTableAdapter = new SqlDataAdapter(“SELECT * FROM [Order Details]”, cnStr);

ये Code तीन DataAdapter Objects Create करता है और चारों DataAdapter Objects में cnStr ConnectionString द्वारा Specified Underlying Database की क्रमश: Products, Customers, Orders Order Details Table के Data को Access व Manipulate करने के लिए SQL Statement Setup करता है। DataAdapter Setup करने के बाद निम्न Statements Execute होते हैं:

// Auto-generate commands.
sqlCBProducts = new SqlCommandBuilder(prodTableAdapter);
sqlCBOrders = new SqlCommandBuilder(ordersTableAdapter);
sqlCBCustomers = new SqlCommandBuilder(custTableAdapter);
sqlCBOrderDetails = new SqlCommandBuilder(orderDetailsTableAdapter);

ये चारों Objects पिछले Section में Create किए गए चारों DataAdapter Object के लिए SelectCommand के आधार पर UpdateCommand, InsertCommand DeleteCommand Properties में Appropriate SQL Statements Fill करने का काम करते हैं, ताकि एक ही DataAdapter का प्रयोग करके Underlying Database में Data को Insert, Update, Delete या Select किया जा सके। चारों DataAdapter Objects के लिए CommandBuilder Setup करने के बाद निम्न Statement Execute होते है:

// Fill tables in DS.
prodTableAdapter.Fill(dsNW, “Products”);
custTableAdapter.Fill(dsNW, “Customers”);
ordersTableAdapter.Fill(dsNW, “Orders”);
orderDetailsTableAdapter.Fill(dsNW, “Order Details”);

ये Statements Execute होकर सभी DataTables को Underlying Data Source पर Appropriate SQL SelectCommand Execute करके DataAdapter द्वारा Data से Fill कर दिया जाता है। जो कि Access व Manipulate करने के लिए हमें हमारे DataSet Object में प्राप्त हो जाता है। DataSet Object में Data प्राप्त करने के बाद अब निम्न Statement Execute होता है:

// Build relations between tables.
BuildTableRelationship();

ये एक Method है, जो DataSet Object में Contained होने वाली चारों DataTables के बीच Relationship Setup करता है, ताकि इन चारों Tables को Frontend Application में भी ठीक उसी तरह से Access व Manipulate किया जा सके, जिस तरह से ये चारों Tables Underlying Database में विभिन्न प्रकार की Relationships से Connected हैं। अन्त में निम्न Statements Execute होते हैं:

// Bind to grids.
dgvProducts.DataSource = dsNW.Tables[“Products”];
dgvCustomers.DataSource = dsNW.Tables[“Customers”];
dgvOrders.DataSource = dsNW.Tables[“Orders”];
dgvOrderDetails.DataSource = dsNW.Tables[“Order Details”];

ये चारों Statements Execute होकर Form पर दिखाई देने वाले चारों DataGridView Controls को DataAdapter Objects के माध्‍यम से Appropriate Data से Fill करते हैं:

Configuring Relationships between DataTable

चूंकि इस Example Program में हम Multiple Tables के Data को एक साथ Access व Manipulate कर रहे हैं, इसलिए इन Tables के बीच की Consistency व Integrity को बनाए रखने के लिए इनके ठीक उसी तरह से Relationship को Maintain करना जरूरी है, जिस तरह की Relationship Underlying Database की विभिन्न Tables के बीच होती है।

इस Relationship को हमारे Program के DataSet Object की तीनों DataTables के बीच Setup करने के लिए ही हमने हमारे Form के Constructor में BuildTableRelationship() Method को Call किया था, जिसे निम्नानुसार Define किया जा सकता है:

        private void BuildTableRelationship()
        {
            // Create CustomerOrder data relation object.
            DataRelation dr = new DataRelation("CustomerOrder",
            dsNW.Tables["Customers"].Columns["CustomerID"],
            dsNW.Tables["Orders"].Columns["CustomerID"]);
            dsNW.Relations.Add(dr);
            
            // Create ProductOrder data relation object.
            dr = new DataRelation("ProductOrder",
            dsNW.Tables["Products"].Columns["ProductID"],
            dsNW.Tables["Order Details"].Columns["ProductID"]);
            dsNW.Relations.Add(dr);

            // Create OrderDetailOrder data relation object.
            dr = new DataRelation("OrderDetailOrder",
            dsNW.Tables["Orders"].Columns["OrderID"],
            dsNW.Tables["Order Details"].Columns["OrderID"]);
            dsNW.Relations.Add(dr);
        }

इस Method के Codes के माध्‍यम से हमारे DataSet में Exist चारों DataTables के बीच Exactly वही Relationship Create हो जाती है, जो Underlying Database की Physical Tables के बीच है। यानी जब निम्न Code Execute होता है:

// Create CustomerOrder data relation object.
DataRelation dr = new DataRelation(“CustomerOrder”,
dsNW.Tables[“Customers”].Columns[“CustomerID”],
dsNW.Tables[“Orders”].Columns[“CustomerID”]);
dsNW.Relations.Add(dr);

तब DataRelation Type का dr नाम का एक Object Create होता है, जिसके Constructor में पहले Parameter के रूप में Relationship के नाम को Specify किया गया है, जबकि दूसरे Parameter के रूप में Parent Column यानी Master Table के Primary Key Column को Specify किया है, जबकि तीसरे Parameter के रूप में Child Column या Detail Table के Foreign Key को Specify किया है।

परिणामस्वरूप इस Relationship के Execute होने पर क्योंकि एक Customer कई Orders Place कर सकता है, इसलिए Customers Table के Primary Key Column को Constructor के दूसरे Parameter के रूप में Specify किया गया है जबकि Orders Table के CustomerID Column को Detailed या Foreign Column के रूप में Specify किया गया है।

इसी तरह से अन्य दोनों Relationships में एक Product, Multiple Order Details में Appear हो सकता है, इसीलिए इस Relationship को निम्न Code द्वारा Configure किया गया है:

// Create ProductOrder data relation object.
dr = new DataRelation(“ProductOrder”,
dsNW.Tables[“Products”].Columns[“ProductID”],
dsNW.Tables[“Order Details”].Columns[“ProductID”]);
dsNW.Relations.Add(dr);

जबकि एक Order में Multiple Products की Detail हो सकती है, इसलिए इस Relationship को निम्नानुसार Code द्वारा Specify किया गया है:

// Create OrderDetailOrder data relation object.
dr = new DataRelation(“OrderDetailOrder”,
dsNW.Tables[“Orders”].Columns[“OrderID”],
dsNW.Tables[“Order Details”].Columns[“OrderID”]);
dsNW.Relations.Add(dr);

इतना काम करने के बाद यदि हम चाहें तो इस Example Database Application को Compile करके Run कर सकते हैं, जिसके Run होने पर हमें हमारा Form विभिन्न Data से Filled होकर निम्नानुसार दिखाई देगा:

Multi-Table C# DataSet Object with Relationship - Hindi

Updating Underlying Database Tables

चूंकि पिछले Code तक Form के विभिन्न DataGridView Controls में Underlying Database से आने वाले Data के Fill होने का काम हो चुका है। इसलिए अन्तिम काम के रूप में हमें हमारी Multiple Tables के इस Application में Form पर दिखाई देने वाले विभिन्न DataGridView Controls में किए गए Changes को Underlying Database की Physical Tables में Update करने के लिए केवल Update Logic Define करना है।

क्योंकि यदि हम चाहें तो इन DataGridView Controls में नया Record Add कर सकते हैं, किसी पहले से Exist Record के Data को Modify कर सकते हैं अथवा किसी Record को Select करके Keyboard के “Delete” Button का प्रयोग करके किसी Record को Delete भी कर सकते हैं।

लेकिन इस Form पर किए गए किसी भी Interaction का प्रभाव Underlying Database की Physical DataTables पर तभी पडेगा, जब हम Form पर दिखाई देने वाले Update Database Button पर Click करेंगे। इसलिए इस Button के Click Event Handler को हम निम्नानुसार Specify करते हुए Form पर किए गए Changes को Underlying Database की Tables में Update कर सकते हैं:

        private void btnUD_Click(object sender, EventArgs e) 
        {
            try
            {
                prodTableAdapter.Update(dsNW, "Products");
                custTableAdapter.Update(dsNW, "Customers");
                ordersTableAdapter.Update(dsNW, "Orders");
                ordersTableAdapter.Update(dsNW, "Order Details");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

जब हम Multiple Tables के साथ प्रक्रिया कर रहे होते हैं, तब Data को Update करने के लिए Define किए जाने वाले Logic में हमें मूल रूप से केवल एक ही बात ध्‍यान में रखनी होती है कि हमेंशा Master Table से Related DataAdapter Object के Code को पहले Specify किया जाए।

क्योंकि Detail Table में तभी Record Insert हो सकता है, जबकि उससे Associated कोई Record Master Table में Exist हो, लेकिन Master Table में Record Insert करते समय ये जरूरी नहीं होता, कि Detailed Table में भी कोई Record हो, जो कि Master Record से Associated हो।

यानी हम जानते हैं कि Products Customers Tables, Master या Parent Table हैं, जिनमें किसी Record को Insert करने के लिए किसी Detailed Table में Record Insert करना जरूरी नहीं होता। लेकिन Orders व “Order Details” Tables, Detailed या Child Tables हैं।

इसलिए किसी Orders Table में तभी कोई Record Insert किया जा सकता है, जबकि उससे Associated कोई Master Record जरूर हो। इसी तरह से Order Details Table में उसी स्थिति में कोई Record Insert किया जा सकता है, जबकि उससे Associated कोई Orders Record जरूर हो।

सरल शब्दों में समझें, तो Order तभी हो सकता है, जबकि उसे Place करने वाला Customer पहले से Exist हो, लेकिन Customer के होने का मतलब ये नहीं है, कि उसने Order जरूर Place किया हो।

इसी तरह से Order Details में किसी Product की Information तभी हो सकती है, जबकि वह Product पहले से Exist हो, लेकिन Product के होने का मतलब ये नहीं है, कि उसे किसी Order Details में जरूरत Specify किया गया हो। इसलिए यदि हम हमारे उपरोक्त Code को निम्नानुसार Specify कर दें, जिसमें “Orders” Table के DataAdapter से सम्बंधित Statement को पहले Specify किया गया हो-

ordersTableAdapter.Update(dsNW, “Orders”);
prodTableAdapter.Update(dsNW, “Products”);
custTableAdapter.Update(dsNW, “Customers”);
ordersTableAdapter.Update(dsNW, “Order Details”);

और हम एक ऐसा Order Record Insert करें, जिससे Associated कोई Customer या Product Record Underlying Database की Customer व Product Table में पहले से Exist न हो, तो इस प्रकार का Code Execute होते ही Error Generate करेगा।

क्योंकि Orders Table में Record Insert करते ही Compiler उस Customer के ID को खोजेगा, जिसने Order Place किया है और यहां हम ये मान रहे हैं कि जिस Customer ने Order Place किया है, उसकी Entry “Customers” Table में तब होगी, जब Customers Table से सम्बंधित DataAdapter Statement Execute होगा, जो कि निम्नानुसार है:

custTableAdapter.Update(dsNW, “Customers”);

इसलिए इस प्रकार की Error Generate न हो, इस बात को Ensure करने का सबसे बेहतर तरीका यही है कि हम हमेंशा Master Table से Related Statements को पहले Specify किया जाए और Detail Tables से सम्बंधित Statements को बाद में।

इसीलिए इस Event Handler में हमने Customers व Products Table को सबसे पहले Update किया है। फिर Orders Table को और अन्त में Order Details Table को Update किया है, क्योंकि Order Details Table पूरी तरह से Orders Table पर Depend है और Orders Table पूरी तरह से Customers व Products Table पर Depend है।

Navigation between Related Tables

चूंकि एक Multiple Table से सम्बंधित Form में कई Tables के Data को एक साथ Access व Manipulate करना होता है, इसलिए उस स्थिति में Data Consistency व Integrity बनाए रखने के लिए DataRelation Object हमारे लिए काफी उपयोगी साबित होता है। क्योंकि इस Object का प्रयोग करके हम Related Tables के Data को Programmatically Access व Manipulate कर सकते हैं।

यानी यदि हम किसी Customer के Record को Customers Table से Delete करते हैं, तो इसका मतलब ये है कि हम उस Customer से Related सभी Orders को भी Delete करना चाहते हैं, जबकि उस Delete होने वाले Customer द्वारा Place किए गए सभी Orders की Information Orders Table में है, जो कि Customers Table से DataRelation Object के माध्‍यम से Related है।

इसी प्रकार से Customer द्वारा Place किए गए है Order में Multiple Products की Details हो सकती है। इसलिए यदि Customer को Delete किया जाता है, तो उससे Associated सभी Orders के Delete होने के साथ ही हर Order के साथ Associated सभी Products की Details यानी Order Details भी Delete होना चाहिए। यानी जब हमें इस प्रकार की Functionality को Maintain करना होता है, तब DataRelation Object हमारे लिए काफी उपयोगी साबित होता है।

इस प्रकार की Professional Functionality प्राप्त करने के लिए हम हमारे Form को निम्नानुसार Modify कर सकते हैं, जिस पर एक TextboxButton Control के माध्‍यम से हम किसी Particular ID वाले Customer के Record को Select करते हैं और उस Selected Customer से Associated OrdersOrder Details की Information से ही Form पर दिखाई देने वाले विभिन्न DataGridView Controls को Fill करते हैं:

Multi-Table C# DataSet Object with Relationship - Hindi

इस Updated UI द्वारा हम एक Custer के CustomerID को Textbox में Enter करके जैसे ही “Get Order Details” Button पर Click करते हैं, उस Customer के सभी Orders की Information से dgvOrders नाम का DataGridView Control Fill हो जाता है। यानी हमें केवल उस Particular Customer के सभी व्तकमते ही दिखाई dgvOrders Control में दिखाई देते हैं। इस जरूरत को पूरा करने के लिए हम निम्नानुसार Event Handler Code लिख सकते हैं:

        private void btnGetOrderDetails_Click(object sender, EventArgs e)
        {
            DataTable dtOrd = dsNW.Tables["Orders"].Clone();
            DataRow[] drCust = null;
            DataRow[] drOrd = null;

            // Now based on custID, get the correct row in Customers table.
            drCust = dsNW.Tables["Customers"].Select(string.Format("CustomerID = '{0}'", this.txtCustomerID.Text)); 

            // Navigate from Customers table to Orders table.
            drOrd = drCust[0].GetChildRows(dsNW.Relations["CustomerOrder"]);

            // Navigate from Customers table to Orders table.
            foreach (DataRow dr in drOrd)
            {
                dtOrd.ImportRow(dr);
            } 
            dgvOrders.DataSource = dtOrd;
        }

इस Method के Code में हमने सबसे पहले dtOrd नाम का एक DataTable Object Create किया है, जिसका Schema हमारी “Orders” नाम की Table के Exactly समान बनाए रखने के लिए ही हमने निम्न Statement का प्रयोग करते हुए Orders DataTable का Clone Create किया है:

DataTable dtOrd = dsNW.Tables[“Orders”].Clone();

फिर हमने drCust drOrd नाम के दो DataRow Objects Create किए हैं और उन्हें null Value से Initialize किया है। फिर निम्न Statement Execute होता है:

// Now based on custID, get the correct row in Customers table.
drCust = dsNW.Tables["Customers"].Select(string.Format("CustomerID = '{0}'", this.txtCustomerID.Text));

इस Statement में हमने हमारे DataTable Object के साथ Select() Method को Use किया है। ये Method एक प्रकार से SQL Statement के WHERE Clause को Represent करता है। यानी यदि हम निम्नानुसार SQL Statement लिखें:

SELECT * FROM Customers WHERE CustomerID=’ABC’

इसी Statement को उपरोक्तानुसार Statement द्वारा Replace किया गया है, जहां हमने dsNW.Tables[“Customers”] Statement द्वारा “SELECT * FROM Customers” का काम पूरा किया है, जबकि Select() Method में String Parameter के रूप में “CustomerID=’ABC'” Specify करने का वही मतलब है, जो SQL Statement में WHERE CustomerID=’ABC’ का होता हैं।

इस प्रकार से यदि हम हमारे पिछले Program के पूरे Code को देखें, तो हमारा पूरा Program Code कुछ निम्नानुसार होगा:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using System.Configuration;

namespace WorkingWithMultipleTables
{
    public partial class frmMultipleTables : Form
    {
        // Form-wide DataSet.
        private DataSet dsNW = new DataSet("Northwind");

        // Make use of command builders to simplify data adapter configuration.
        private SqlCommandBuilder sqlCBProducts;
        private SqlCommandBuilder sqlCBCustomers;
        private SqlCommandBuilder sqlCBOrders;
        private SqlCommandBuilder sqlCBOrderDetails;

        // Our data adapters (for each table).
        private SqlDataAdapter prodTableAdapter;
        private SqlDataAdapter custTableAdapter;
        private SqlDataAdapter ordersTableAdapter;
        private SqlDataAdapter orderDetailsTableAdapter;

        // Form-wide connection string.
        private string cnStr = string.Empty;

        public frmMultipleTables()
        {
            InitializeComponent();
            // Get connection string from *.config file.
            cnStr = ConfigurationManager.ConnectionStrings["NWSQLProvider"].ConnectionString;

            // Create adapters.
            prodTableAdapter = new SqlDataAdapter("Select * from Products", cnStr);
            custTableAdapter = new SqlDataAdapter("Select * from Customers", cnStr);
            ordersTableAdapter = new SqlDataAdapter("Select * from Orders", cnStr);
            orderDetailsTableAdapter = new SqlDataAdapter("Select * FROM [Order Details]", cnStr);
            
            // Auto-generate commands.
            sqlCBProducts = new SqlCommandBuilder(prodTableAdapter);
            sqlCBOrders = new SqlCommandBuilder(ordersTableAdapter);
            sqlCBCustomers = new SqlCommandBuilder(custTableAdapter);
            sqlCBOrderDetails = new SqlCommandBuilder(orderDetailsTableAdapter);

            // Fill tables in DS.
            prodTableAdapter.Fill(dsNW, "Products");
            custTableAdapter.Fill(dsNW, "Customers");
            ordersTableAdapter.Fill(dsNW, "Orders");
            orderDetailsTableAdapter.Fill(dsNW, "Order Details");

            // Build relations between tables.
            BuildTableRelationship();

            // Bind to grids.
            dgvProducts.DataSource = dsNW.Tables["Products"];
            dgvCustomers.DataSource = dsNW.Tables["Customers"];
            dgvOrders.DataSource = dsNW.Tables["Orders"];
            dgvOrderDetails.DataSource = dsNW.Tables["Order Details"];
        }

        private void BuildTableRelationship()
        {
            // Create CustomerOrder data relation object.
            DataRelation dr = new DataRelation("CustomerOrder",
            dsNW.Tables["Customers"].Columns["CustomerID"],
            dsNW.Tables["Orders"].Columns["CustomerID"]);
            dsNW.Relations.Add(dr);
            
            // Create ProductOrder data relation object.
            dr = new DataRelation("ProductOrder",
            dsNW.Tables["Products"].Columns["ProductID"],
            dsNW.Tables["Order Details"].Columns["ProductID"]);
            dsNW.Relations.Add(dr);

            // Create OrderDetailOrder data relation object.
            dr = new DataRelation("OrderDetailOrder",
            dsNW.Tables["Orders"].Columns["OrderID"],
            dsNW.Tables["Order Details"].Columns["OrderID"]);
            dsNW.Relations.Add(dr);
        }

        private void btnUD_Click(object sender, EventArgs e)
        {
            try
            {
                prodTableAdapter.Update(dsNW, "Products");
                custTableAdapter.Update(dsNW, "Customers");
                ordersTableAdapter.Update(dsNW, "Orders");
                ordersTableAdapter.Update(dsNW, "Order Details");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Dispose();
        }

        private void btnGetOrderDetails_Click(object sender, EventArgs e)
        {
            DataTable dtOrd = dsNW.Tables["Orders"].Clone();
            DataRow[] drCust = null;
            DataRow[] drOrd = null;

            // Now based on custID, get the correct row in Customers table.
            drCust = dsNW.Tables["Customers"].Select(
string.Format("CustomerID = '{0}'", this.txtCustomerID.Text));

            // Navigate from Customers table to Orders table.
            drOrd = drCust[0].GetChildRows(dsNW.Relations["CustomerOrder"]);

            // Navigate from Customers table to Orders table.
            foreach (DataRow dr in drOrd)
            {
                dtOrd.ImportRow(dr);
            } 
            dgvOrders.DataSource = dtOrd;
        }
    }
}

 

हालांकि इस Program में हमने केवल CustomerID के आधार पर Orders की List को Retrieve किया है। ठीक इसी तरीके को Use करके हम Order के आधार पर Order Details की Information तथा Product के आधार पर Order Details की Information को भी Access and Manipulate कर सकते हैं व अपने Application को ज्यादा Professional बना सकते हैं।

C# Class Library Example for Common Functionality
Working with Strongly Typed using Data Source

ADO.NET with C# in Hindi - BccFalna.com: TechTalks in Hindi ये Article इस वेबसाईट पर Selling हेतु उपलब्‍ध EBook ADO.NET with C# in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी। 

ADO.NET with C# in Hindi | Page:501 | Format: PDF

BUY NOW GET DEMO REVIEWS