DataTable Select C# Example: DataTable Object वास्तव में किसी DataSet Object में Contained एक In-Memory Table होता है, जिसे Underlying Database के किसी Physical Table के Data से भी Fill किया जा सकता है अथवा इसे एक से एक से अधिक Tables की Joining से Generate होने वाले Resultset से भी Fill किया जा सकता है।
इसका मतलब ये है कि DataTable वास्तव में एक ऐसा In-Memory Data Structure होता है, जो Rows व Columns के Collection द्वारा किसी Table के Data को Logically Tabular Format में Represent करता है।
इतना ही नहीं जैसाकि अन्य Chapters में हमने Discuss किया है, DataSet की विभिन्न Tables पर हम ठीक उसी प्रकार से विभिन्न प्रकार के Constraints Apply कर सकते हैं, जिस प्रकार से वास्तविक RDBMS Software पर करते हैं। यानी हम इन DataTables पर Primary Key व Foreign Key Constraint Apply करके दो DataTables के बीच ठीक उसी प्रकार से Relationship भी Maintain कर सकते हैं, जिस प्रकार से वास्तविक RDBMS Software में वास्तविक Tables के बीच Relationship Configure किया जाता है।
साथ ही जिस तरह से हम किसी Table के Data को विभिन्न तरीकों से Access व Manipulate करने के लिए विभिन्न प्रकार के Searching, Sorting व Filtering Operations Perform करते हैं, ठीक उसी प्रकार से हम DataSet Object में Contained विभिन्न DataTables पर भी विभिन्न प्रकार के Searching, Sorting व Filtering Operations Perform करके विभिन्न प्रकार की जरूरतों को पूरा करने के लिए इन्हें विभिन्न तरीकों से Access व Manipulate कर सकते हैं।
लेकिन जब हम DataTable पर Searching, Sorting या Filtering Operation Perform कर रहे होते हैं, तब हम DataTables पर ठीक उसी प्रकार की SQL Query Language आधारित SQL Queries Use नहीं कर सकते, जिस प्रकार की SQL Query हम वास्तविक Tables पर Execute करते हैं। बल्कि DataTables के साथ इस प्रकार के Operations Perform करते समय हमें ADO.NET द्वारा Provide किए जाने वाले Objects व Techniques को Use करते हुए ही Searching, Sorting व Filtering Operations Perform करने पडते हैं।
Finding Single Required Row
कई बार हमें किसी Particular Key Value के आधार पर अपने DataTable में किसी Single Record को Access करने की जरूरत होती है। जब हम Connected Mode में होते हैं, तब इस प्रकार की जरूरत को पूरा करने के लिए हम Underlying Database की किसी भी Table पर सीधे ही SQL Query Fire कर देते हैं, लेकिन जब हम Disconnected Mode में होते हैं, तब हम DataTables सीधे ही SQL Query Execute नहीं कर सकते।
इसलिए इस जरूरत को पूरा करने के लिए हमें ADO.NET के DataTable.Rows या DataRowCollection Object को Use करना होता है, जिसके साथ Particular Key को Specify करते हुए Record की Searching के लिए हम Find() Method का प्रयोग कर सकते हैं।
जब हम किसी DataTable पर Find() Method का प्रयोग करते हुए किसी Record को Find करना चाहते हैं, तब हमें इस बात का ध्यान रखना होता है कि Find() Method केवल एक Primary Key Column को ही Parameter की तरह Accept करता है और Key Value के रूप में Specified Value से Matching Value वाले Record को एक DataRow Object के रूप में Return करता है।
इसलिए जिस DataTable के Records में से हम किसी Particular Record को Find() Method का प्रयोग करते हुए Retrieve करना चाहते हैं, उस DataTable Object में या तो हमें Manually Primary Key Column को Specify करना होता है या फिर हमें उस DataTable के Schema को भी उस स्थिति में Load करना जरूरी होता है, जब हम Normal DataSet के साथ Operate कर रहे होते हैं।
ताकि DataSet Object, अपनी DataTables के Columns की Information को Schema के आधार पर त; कर सके और DataTable का Exactly वैसा ही Structure Create कर सके, जैसा Structure Actual Database में Stored Table का होता है।
हालांकि Strongly Typed DataSet Object Use करने पर हमें इस प्रकार की Schema Related चिन्ता करने की जरूरत नहीं होती है क्योंकि Strongly Typed DataSet Object Crete करते समय Visual Studio स्वयं इन सभी जरूरी बातों का ध्यान रखता है और हमने हमारे इस Chapter में एक Strongly Typed DataSet Create किया है।
यहां एक और ध्यान रखने वाली बात ये है कि जब हम Normal DataSet Create करते हैं, तो उसमें Contained DataTable के Row को Find() Method का प्रयोग करके Find करने पर जो Record Return होता है, उसे DataRow Type के Object में Hold किया जाता है। लेकिन जब हम Strongly Typed DataSet Object के साथ Operate कर रहे होते हैं, तो किसी DataTable से Return होने वाले Row को Hold करने के लिए हमें Strongly Typed DataRow Type का Object की Create करना होता है।
इस Concept को समझने के लिए हम हमारे Windows Forms Application Project के Form निम्नानुसार एक Form Design कर सकते हैं:
इस Form पर हमने Customer के सभी Columns को Display करने के लिए एक GroupBox Control में Customer के सभी Columns को Disabled Textbox के रूप में Specify किया है। जबकि Form पर केवल एक ही Textbox Enabled है, जो कि उस Customer का ID Accept करता है, जिसके Record को DataTable से Access करके इस Form पर दिखाई देने वाले Bind Controls में Fill करना है।
जब हम इस Form पर दिखाई देने वाले CustomerID Textbox में किसी Customer का ID Specify करके “Find” Button पर Click करते हैं, तो इस Click Event के Response में निम्नानुसार Click Event Handler Execute होता है:
private void btnFind_Click(object sender, EventArgs e) { dsSSF.CustomersDataTable dtCustomers = new dsSSF.CustomersDataTable(); dsSSFTableAdapters.CustomersTableAdapter daCustomers = new dsSSFTableAdapters.CustomersTableAdapter(); //Fill Customers DataTable with Data daCustomers.Fill(dtCustomers); dsSSF.CustomersRow drRow = dtCustomers.FindByCustomerID(txtCustomerID.Text.ToString()); customerIDTextBox.Text = drRow.CustomerID; companyNameTextBox.Text = drRow.CompanyName; contactNameTextBox.Text = drRow.ContactName; contactTitleTextBox.Text = drRow.ContactTitle; addressTextBox.Text = drRow.Address; cityTextBox.Text = drRow.City; if (drRow.IsNull("Region")) regionTextBox.Text = ""; else regionTextBox.Text = drRow.Region; postalCodeTextBox.Text = drRow.PostalCode; countryTextBox.Text = drRow.Country; phoneTextBox.Text = drRow.Phone; faxTextBox.Text = drRow.Fax; }
इस Event Handler के Execute होते ही सबसे पहले dtCustomers नाम का एक dsSSF.CustomersDataTable Type का Object Create किया है, जो कि Underlying Database के Customers Table के Data को Represent करता है। साथ ही इस DataTable में Data को Fill करने के लिए अथवा DataTable में किए गए Change को Database की Underlying Table में Update करने के लिए हमें एक Strongly Typed DsSSFTableAdapters.CustomersTableAdapter Type के DataAdapter Object की भी जरूरत होती है। इसलिए अगले Statement द्वारा हमने daCustomers नाम का एक DataAdapter Object भी Create किया है।
DataTable व TableAdapter Objects Create करने के बाद हमने अपनी DataTable को निम्न Statement के माध्यम से Underlying Database की Customers Table के Data से Fill किया है:
//Fill Customers DataTable with Data
daCustomers.Fill(dtCustomers);
इस Statement के Execution के साथ ही हमारे DataTable Object में Data Fill हो जाता है। इसलिए जब निम्नानुसार अगला Statement Execute होता है:
dsSSF.CustomersRow drRow =
dtCustomers.FindByCustomerID(txtCustomerID.Text.ToString());
तो ये Statement dsSSF.CustomersRow Type का drRow नाम का एक DataRow Object Create करता है और इस Row में dtCustomers नाम के DataTable Object से उस Row को Search करता है, जिसका Customer ID Form पर दिखाई देने वाले txtCustomerID नाम के Textbox Control में Specify किया गया है।
यदि इस Textbox में जिस Customer ID को Specify किया गया होता है, उस Customer ID से Associated कोई Record यदि dtCustomers नाम के DataTable Object में Exist होता है, तो वह Record इस drRow Object में Load हो जाता है। फिर जब निम्नानुसार आगे के Statements Execute होते हैं:
customerIDTextBox.Text = drRow.CustomerID; companyNameTextBox.Text = drRow.CompanyName; contactNameTextBox.Text = drRow.ContactName; contactTitleTextBox.Text = drRow.ContactTitle; addressTextBox.Text = drRow.Address; cityTextBox.Text = drRow.City; if (drRow.IsNull("Region")) regionTextBox.Text = ""; else regionTextBox.Text = drRow.Region; postalCodeTextBox.Text = drRow.PostalCode; countryTextBox.Text = drRow.Country; phoneTextBox.Text = drRow.Phone; faxTextBox.Text = drRow.Fax;
तो इन Statements के Execution के कारण हमें drRow Object में Stored Rows के सभी Columns उसके साथ Bind Controls में निम्न चित्रानुसार दिखाई देने लगते हैं:
इस Code Segment में यदि हम ध्यान से देखें, तो Region Column के Data को निम्नानुसार एक if Statement Block के माध्यम से Textbox Control के साथ Bind किया है:
if (drRow.IsNull("Region")) regionTextBox.Text = ""; else regionTextBox.Text = drRow.Region;
Region Column को इस Code के माध्यम से इसलिए Specify किया है, क्योंकि Region Column में हम Null Value Store कर सकते हैं। चूंकि Underlying Database की Customers Table में तो Unknown Value को Represent करने के लिए null शब्द का प्रयोग किया जा सकता है, लेकिन जब हम ADO.NET का प्रयोग करते हुए DataTables Create करते हैं, तो DataTable में Unknown Value को null से Represent नहीं किया जाता, बल्कि सभी Null Values को System.DBNull Value से Represent किया जाता है।
इसलिए जब हम Strongly Typed drRow Object में Strongly Typed DataTable के किसी Record को Retrieve करते हैं, तो उस Record में Region नाम का वह Column भी होता है, जिसमें एक System.DBNull Value Stored है या हो सकती है और हम किसी System.DBNull Value को एक Empty String की तरह किसी Textbox Control की Text Property में Assign नहीं कर सकते। यदि हम ऐसा करने की कोशिश करते हैं, तो .NET Compiler Error Generate करता है।
इसलिए regionTextbox Control की Text Property में DataRow Object के Region Column के मान को Assign करने से पहले हमने इस बात को Check किया है कि Assign किया जाने वाला मान Null Value है या नहीं।
यदि Assign किया जाने वाला मान Null Value हो सकता है, तो उस स्थिति में हम किसी Textbox की Text Property में Directly DBNull मान Assign नहीं कर सकते। इसलिए Assignment से पहले Region को इस बात के लिए Check किया गया है कि उसमें DBNull Value है या नहीं।
जब हम DataTable के साथ Interact कर रहे होते हैं, तब यदि किसी Table Column में Null Value Assign किया जा सकता है, तो उस Column की Value को किसी Bind Control में Assign करने से पहले इस बात के लिए जरूर Check करना चाहिए कि उसमें DBNull Value है या नहीं।
यानी Primary Key, Unique, Not Null जैसे Constraint Columns को छोडकर अन्य सभी सामान्य Columns के साथ हमें उपरोक्तानुसार if Statement का प्रयोग करते हुए DBNull Value को जरूर Check करना चाहिए, ताकि Null Value के कारण Generate होने वाली किसी भी तरह की Error Generate न हो।
Retrieving Multiple Rows
पिछले उदाहरण में हमने केवल एक Single Record को Find करने के तरीके के बारे में जाना है। जबकि अक्सर हमें किसी Particular Condition से Match होने वाली सभी Rows को Retrieve करके उनके साथ किसी Specific Operation को Perform करना होता है। जब हम Physical Database के साथ Interact कर रहे होते हैं, तब हम SQL Query में WHERE Clause का प्रयोग करके अपनी Condition को Specify कर सकते हैं। जैसे:
SELECT * FROM Customers WHERE LastName LIKE ‘%ma’;
ये SQL Statement Customers Table के उन सभी Customers के Records को Return करेगा, जिनके LastName का अन्त “ma” से होता हो। जैसे Sharma, Verma, etc…, लेकिन जब हम DataTable के साथ काम करते हैं, तब हम ठीक इसी तरह की SQL Query का प्रयोग नहीं कर सकते, लेकिन ADO.NET हमें Exactly WHERE Clause के Alternative के रूप में Select() Method Provide करता है, जिसमें एक String Format में हम Exactly उसी Condition को Specify कर सकते हैं, जिसे WHERE Clause के बाद Specify करते हैं। जैसे:
DataRow[] drArray = dtCustomers.Select(“LastName LIKE ‘%ma'”);
जब ये Statement Execute होता है तो dtCustomers नाम के DataTable के वे Records Select होते हैं, जिनके LastName का अन्त “ma” से होता है और वे सभी Selected Rows, drArray नाम के Array में Store हो जाते हैं, जिन्हें हम हमारी जरूरत के अनुसार उपयोग में ले सकते हैं। इस Statement को Practically Use करते हुए समझने के लिए हम हमारे पिछले Form को ही निम्नानुसार Redesign कर सकते हैं:
इस Form पर हमने एक DataGridView Control Place किया है, जो कि Select() Method के Execution से Select होने वाले सभी Records को Show करने का काम करता है। जबकि एक Textbox है, जिसमें हम WHERE Clause के बाद Specify की जाने वाली Condition को Specify करते हैं।
इस Form पर स्थित इस Textbox में WHERE Clause Specify करने के बाद जब हम “Find” Button पर Click करते हैं, तो इस Button के Click Event को Handle करने के लिए निम्नानुसार Click Event Handler Execute होता है:
private void btnSelect_Click(object sender, EventArgs e) { dsSSF.CustomersDataTable dtCustomers = new dsSSF.CustomersDataTable(); dsSSFTableAdapters.CustomersTableAdapter daCustomers = new dsSSFTableAdapters.CustomersTableAdapter(); //Fill Customers DataTable with Data daCustomers.Fill(dtCustomers); DataRow[] drRows = dtCustomers.Select(txtWherePart.Text); dgvCustomers.DataSource = drRows; }
जैसाकि हम देख सकते हैं कि इस Event Handler व पिछले Program के Event Handler में कोई विशेष अन्तर नहीं है और पिछले Event Handler की तरह ही इस Event Handler में भी हमने daCustomers नाम का एक Strongly Typed DataSet Object Create किया है और उसमें Underlying Database की Customers Table के Data को Fill किया है। dtCustomers में जब Data Fill हो जाता है, तब निम्न Statement Execute होता है:
DataRow[] drRows = dtCustomers.Select(txtWherePart.Text);
ये Statement Execute होते ही dtCustomers नाम के DataTable Object के लिए Select Method Execute होता है जिसमें Form पर दिखाई देने वाले txtWherePart नाम के Textbox की Text Property में Stored String को Parameter की तरह Pass किया जाता है।
परिणामस्वरूप Select Method इस Textbox में Specified Condition के आधार पर DataTable से Matching Records को Select करता है और Selected Records को एक DataRow Object के रूप में Return करता है, जिन्हें Hold करने के लिए drRows नाम का एक DataRow Object Crete किया गया है।
dtCustomers नाम के DataTable से जो भी Rows Return होकर drRows Object में Store होते हैं, उन्हें निम्न Statement के माध्यम से Form पर दिखाई देने वाले DataGridView Control की DataSource Property को Assign कर दिया गया है:
dgvCustomers.DataSource = drRows;
परिणामस्वरूप इस Statement के Execute होते ही Form पर स्थित DataGridView Control में केवल वे Records Display होने लगते हैं, जो कि Form पर Placed Textbox में Specified Condition से Match करते हैं।
इस तरह से यदि हम ‘Brazil’ में रहने वाले सभी Customers को DataTable से Retrieve करके DataGridView Control में Render करना चाहें, तो Find Button को Click करने पर हमें प्राप्त होने वाला Output कुछ निम्नानुसार होगा:
हालांकि जब हम इस तरह से Records को Retrieve करते हैं, तब हमें इस बात का ध्यान रखना जरूरी होता है कि यदि यदि Return होने वाले Records के Columns में DBNull Value Stored हो, तो हमें Exception Face करना पडता है।
जब हम Select() Method Use करते हैं, तब हमें Select() Method के कुल 5 अलग Overloaded Versions प्राप्त होते हैं, जो हमारी अलग-अलग तरह की Requirements को पूरा करते हैं।
यानी यदि हम चाहें तो Select Method के दूसरे Parameter के रूप में निम्नानुसार तरीके से Statement Specify करके Return होने वाले Records को Ascending या Descending Order में Return कर सकते हैं:
DataRow[] drRows = dtCustomers.Select(txtWherePart.Text, “Country ASC”);
इस Statement के Execute होने पर Return होने वाला Resultset Country-Wise Ascending Order में Return होगा। इसी तरह से हम किसी भी Column/Columns के साथ ASC के स्थान पर DESC Specify करके Descending Order में Records Retrieve कर सकते हैं।
जैसाकि हमने पिछले Chapters में जाना है कि Disconnected Mode में हम जब किसी DataTable/DataSet में विभिन्न प्रकार के Changes Perform करते हैं, तो हर प्रकार के Change को Reflect करने के लिए हर Row के साथ एक Specific Enum Value (Added, Detached, Modified, etc…) Associate कर दिया जाता है। Select() Method के तीसरे Version को Use करके हम इन Values के आधार पर Records का Selection कर सकते हैं। जैसे:
DataRow[] drRows = dtCustomers.Select( txtCustomerID.Text, "Country ASC", DataViewRowState.Added );
जब इस Statement का Execution होता है, तो dtCustomers नाम के DataTable से केवल वे Records Retrieve होते हैं, जिन्हें Newly Add किया गया है।
ये Article इस वेबसाईट पर Selling हेतु उपलब्ध EBook ADO.NET with C# in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी।
ADO.NET with C# in Hindi | Page:501 | Format: PDF