DataSet Object हमें Underlying Data Source से Fetch होने वाले Data को Disconnected Fashion में Store करने की सुविधा देता है। लेकिन Underlying Data Source से DataSet Object में Store होने वाले Data पर हम हमारे Frontend Application के माध्यम से अपनी जरूरत के अनुसार काफी Changes करते हैं और उन Changes को फिर से Underlying Data Source में Permanently Store करने के लिए DataAdapter Object के Update() Method का प्रयोग करते हुए Underlying Data Source से फिर से Connect करते हैं।
DataAdapter Object के Update() Method के Call करने मात्र से हमारे Frontend Application को भी इस बात का ज्ञान रहता है, कि DataSet Object के किन Rows में INSERT, UPDATE या DELETE किए गए Records को Underlying Data Source में Store किया जा रहा है। Connect, Fetch, Disconnect, Modify, Reconnect व Persist Changes के इस Sequence में कई स्थितियों को ध्यान में रखना जरूरी होता है, जो कि निम्नानुसार हैं:
- हमें उन Rows को ध्यान में रखना होता है, जिन्हें DataSet Object में Insert, Update या Delete किया गया होता है।
- Application को Concurrently Use करने के कारण अन्य Users भी इसी समय के दौरान, जबकि हम हमारे Application के DataSet Object के Rows में Changes करते हैं, अपने DataSet Object में किए गए Changes को समान Underlying Data Source में Save किया हो सकता है। इसलिए हमारी SQL Query द्वारा जो Disconnected Data हमारे DataSet Object में Stored है, वह हो सकता है कि अन्य Users के Data Save करने की वजह से अब Valid न हो।
- हमारे Disconnected DataSet में Insert किए गए नए Records के लिए Generate होने वाली Key Values भी सम्भवतया Valid न हो, क्योंकि जो Key हमारे द्वारा Inserted Records को Allot की गई है, वही Key अन्य Users द्वारा Inserted Records के लिए भी Allotted हो सकती है, जो कि पहले से ही Underlying DataSource में Save हो चुकी है।
- जब हम हमारे Disconnected DataSet के Data को Update() Method द्वारा Update करते हैं, तो हमें हमारे Frontend Application में फिर से Updated Data को Fetch करने की भी जरूरत होती है, ताकि हमारे Application में Latest Updated व Refreshed Data Available हों।
इन विभिन्न प्रकार के Issues को Handle करने के लिए DataSet, DataTable व ADO.NET के Disconnected Part को Define करने वाले विभिन्न प्रकार के अन्य Objects कई Special Features Provide करते हैं, जहां DataRow.RowState Property इन सभी प्रकार के Issues को Handle करने में सबसे महत्वपूर्ण Role Play करता है। DataRow.RowState Property, DataRowState Enumeration Type की Property होता है, जिसमें निम्न में से कोई एक मान Store हो सकता है:
Detached (1)
किसी भी Particular समय पर एक DataRow केवल एक DataTable के साथ Connected हो सकता है। जबकि यदि कोई DataRow, किसी भी DataTable से Connected न हो, तो उस Row की State Property में Detached मान होता है।
UnChanged (2)
यदि किसी DataRow में ये मान Stored हो, तो ये इस बात का Indication है कि Underlying DataSource से जो Data Fetch किया गया था, उस Data में Frontend Application द्वारा कोई Change Perform नहीं किया गया है।
Added (4)
जब हम DataSet Object में Frontend Application द्वारा कोई नया Row Insert करते हैं, तो उस Row की State Property में ये मान होता है। जब DataAdapter के Update() Method को DataSet Object के Data को Underlying DataSource में Save करने के लिए Use किया जाता है, तब इस मान वाले Rows के लिए DataAdapter Object, InsertCommand Execute करता है।
Deleted (8)
जब हम DataSet Object में Frontend Application द्वारा Underlying DataSource से आने वाले किसी Row को Delete कर देते हैं, तो उस Row की State Property में ये मान Store हो जाता है। परिणामस्वरूप जब DataAdapter के Update() Method को DataSet Object के Data को Underlying DataSource में Save करने के लिए Use किया जाता है, तब इस मान वाले Rows के लिए DataAdapter Object, DeleteCommand Execute करता है।
Modified (16)
जब हम DataSet Object में Frontend Application द्वारा Underlying DataSource से आने वाले किसी Row के Data को Modify करते हैं, तो उस Row की State Property में ये मान Store हो जाता है। परिणामस्वरूप जब DataAdapter के Update() Method को DataSet Object के Data को Underlying DataSource में Save करने के लिए Use किया जाता है, तब इस मान वाले Rows के लिए DataAdapter Object, UpdateCommand Execute करता है।
यानी यदि हम चाहें, तो किसी DataSet Object की किसी DataTable के किसी भी Row की इस State Property में माध्यम से हम इस बात का पता लगा सकते हैं कि उस Row के साथ Frontend Application द्वारा किस प्रकार का Operation Perform किया गया है अथवा किस Row के लिए DataAdapter के Update() Method को Use करने पर कौनसा Command (InsertCommand, UpdateCommand, DeleteCommand) Execute होगा। एक Example Program द्वारा हम State Management की इस व्यवस्था को ज्यादा बेहतर तरीके से समझ सकते हैं, जो कि निम्नानुसार है:
using System; using System.Data; using System.Data.SqlClient; namespace StateManagement { class Program { static void Main(string[] args) { string connectionString= "Data Source=KULDEEP\\SQLSERVEREXPRESS; Initial Catalog=Northwind; Integrated Security=True"; using (SqlConnection testConnection = new SqlConnection(connectionString)) { SqlCommand testCommand = testConnection.CreateCommand(); testCommand.CommandText = "SELECT * FROM Employees"; SqlDataAdapter sqlDa = new SqlDataAdapter(testCommand); DataTable empTable = new DataTable("Employees"); sqlDa.Fill(empTable); DisplayRowStates("Row states for a freshly filled DataTable:", empTable); } } static void DisplayRowStates(string msg, DataTable table) { Console.WriteLine("Employees Rows"); foreach (DataRow dr in table.Rows) { Console.WriteLine(dr[0].ToString() +": "+ dr[1].ToString() +": "+ dr.RowState.ToString()); } } } }
जब हम इस Program को Run करते हैं, तो हमें निम्नानुसार Output प्राप्त होता है:
Row states for a freshly filled DataTable: 1 : Davolio : Unchanged 2 : Fuller : Unchanged 3 : Leverling : Unchanged 4 : Peacock : Unchanged 5 : Buchanan : Unchanged 6 : Suyama : Unchanged 7 : King : Unchanged 8 : Callahan : Unchanged 9 : Dodsworth : Unchanged
चूंकि इस Program में हमने केवल Northwind Database के Employees Table के सभी Rows के Data को DataTable Object में Load किया है और फिर DisplayRowStates() Method को Call करके सभी Rows के EmployeeID व LastName Fields के Data को Display किया है।
इसलिए इस Display होने वाले Output में किसी भी Record में किसी भी तरह का Modification न होने की वजह से सभी Rows के साथ हमें “Unchanged” मान दिखाई दे रहा है। लेकिन यदि हम इसी Program को निम्नानुसार Modify करें-
using System; using System.Data; using System.Data.SqlClient; namespace StateManagement { class Program { static void Main(string[] args) { string connectionString="Data Source=KULDEEP\\SQLSERVEREXPRESS;Initial Catalog=Northwind;Integrated Security=True"; using (SqlConnection testConnection = new SqlConnection(connectionString)) { SqlCommand testCommand = testConnection.CreateCommand(); testCommand.CommandText = "SELECT * FROM Employees"; SqlDataAdapter sqlDa = new SqlDataAdapter(testCommand); DataTable empTable = new DataTable("Employees"); sqlDa.Fill(empTable); DataRow record; //Modify the Last Name record = empTable.Rows[0]; record["LastName"] = "Mishra"; //Insert New Row record = empTable.NewRow(); record["EmployeeID"] = 100; record["LastName"] = "Sharma"; empTable.Rows.Add(record); //Delete First Row //record = empTable.Rows[10]; //record.Delete(); DisplayRowStates("Row states for a freshly filled DataTable:", empTable); } } static void DisplayRowStates(string msg, DataTable table) { Console.WriteLine(msg); foreach (DataRow dr in table.Rows) { Console.WriteLine(dr[0].ToString() +" :"+ dr[1].ToString() +": "+ dr.RowState.ToString()); } } } } Output: Row states for a freshly filled DataTable: 1 : Mishra : Modified 2 : Fuller : Unchanged 3 : Leverling : Unchanged 4 : Peacock : Unchanged 5 : Buchanan : Unchanged 6 : Suyama : Unchanged 7 : King : Unchanged 8 : Callahan : Unchanged 9 : Dodsworth : Unchanged 100 : Sharma : Added
जब ये Program Run होता है, तब निम्न Code के माध्यम से पहले Row के LastName Column को Modify किया जाता है:
DataRow record; //Modify the Last Name record = empTable.Rows[0]; record["LastName"] = "Mishra";
परिणामस्वरूप दिखाई देने वाले Output में हम देख सकते हैं कि पहले Row के LastName Column का मान Davolio से Change होकर Mishra हो गया है। चूंकि हमने Row को Modify किया है, इसलिए हमें हमारे DataAdapter Object की State Property में इस Row के लिए “Modified” मान प्राप्त होता है। इसी प्रकार से जब निम्नानुसार Code Execute होता है:
//Insert New Row record = empTable.NewRow(); record["EmployeeID"] = 100; record["LastName"] = "Sharma"; empTable.Rows.Add(record);
तो ये Code Execute होने के बाद हमारी DataTable में एक नया Row Insert होता है। इसलिए ये Newly Inserted Row हमारे DataTable के अन्तिम Row के रूप में Add होने के कारण हमें हमारे Output के अन्तिम Row के रूप में उपरोक्तानुसार दिखाई देता है, जिसकी State Property का मान “Added” होता है। क्योंकि ये Record हमारे Application द्वारा Add किया जा रहा है न कि ये Record Underlying DataSource में Exist है।
जब कोई DataRow या DataRowCollection का कोई हिस्सा DataTable के Rows Property के रूप में Associated नहीं होता, उस स्थिति में उस DataRow की RowState Property का मान Detached होता है। उदाहरण के लिए यदि हम हमारे पिछले Program में निम्नानुसार Code लिखें-
//Detached Row record = empTable.NewRow(); record["EmployeeID"] = 101; record["LastName"] = "Verma"; //empTable.Rows.Add(record);
लेकिन जैसाकि इस Code में हम देख सकते हैं कि हमने Newly Create होने वाले Record को DataTable में Add नहीं किया है, इसलिए Create होने वाली इस Row की RowState Property में Value के रूप में Detached मान Stored होगा।
जब हम हमारे DataTable या DataSet में उपरोक्तानुसार नया Row Add करके अथवा किसी पहले से Exist Row को Modify करके किसी प्रकार का Change करते हैं, तो वह Change तब तक Underlying Database में Permanently Store नहीं होता, जब तक कि हम DataAdapter Object के साथ Update() Method का प्रयोग नहीं करते।
जब हम DataAdapter Object के साथ Update() Method को Use करते हैं और empTable Object को इस Method में Parameter की तरह Pass करते हैं, तो DataAdapter Object हमारी empTable के हर Row को Iterate करता है और-
- जिन Rows के साथ Added Value Set होता है, उनके लिए DataAdapter Object InsertCommand() Method को Call करता है।
- जिन Rows के साथ Modified Value Set होता है, उनके लिए DataAdapter Object UpdateCommand() Method को Call करता है।
- जिन Rows के साथ Deleted Value Set होता है, उनके लिए DataAdapter Object DeleteCommand() Method को Call करता है।
क्योंकि Detached Rows, DataTable Object का हिस्सा नहीं होता इसलिए DataAdapter के सभी Rows के इस Iteration के दौरान Detached Rows में किए गए किसी भी Modification को Ignore कर दिया जाता है। जबकि सभी बची हुई Rows के DataRow की RowState Property में कोई न कोई Appropriate मान Stored होता है, जिसके आधार पर ही DataAdapter Object का कोई न कोई Appropriate Command Execute होता है।
DataAdapter की वे Properties, जो कि जरूरी Commands को Hold करता है, DeleteCommand, InsertCommand व UpdateCommand हैं। लेकिन सबसे पहले हमें DeleteCommand, UpdateCommand व InsertCommand Properties को Specify करना होता है। इन Properties में हम Stored Procedure सहित किसी भी Valid SQL Command को Specify कर सकते हैं, लेकिन सरलता बनाए रखने के लिए हम यहां पर SqlCommandBuilder Object को Use करते हुए ही आगे बढ रहे हैं और अपने पिछले Program को ही निम्नानुसार Modify कर रहे हैं:
using System; using System.Data; using System.Data.SqlClient; namespace StateManagement { class Program { static void Main(string[] args) { string connectionString="Data Source=.\\SQLSERVEREXPRESS;Initial Catalog=Northwind;Integrated Security=True"; using (SqlConnection testConnection = new SqlConnection(connectionString)) { SqlCommand testCommand = testConnection.CreateCommand(); testCommand.CommandText = "SELECT * FROM Employees"; SqlDataAdapter sqlDa = new SqlDataAdapter(testCommand); DataTable empTable = new DataTable("Employees"); sqlDa.Fill(empTable); DataRow record; //Modify the Last Name record = empTable.Rows[0]; record["LastName"] = "Mishra"; //Insert New Row record = empTable.NewRow(); record["EmployeeID"] = 100; record["LastName"] = "Sharma"; empTable.Rows.Add(record); //Delete First Row //record = empTable.Rows[10]; //record.Delete(); // Update the changes back to the database. SqlCommandBuilder cmbldr = new SqlCommandBuilder(sqlDa); // Setup Update Command sqlDa.UpdateCommand = cmbldr.GetUpdateCommand(); Console.WriteLine("Update Command: " + sqlDa.UpdateCommand.CommandText); // Setup Insert Command sqlDa.InsertCommand = cmbldr.GetInsertCommand(); Console.WriteLine("Insert Command: " + sqlDa.InsertCommand.CommandText); // Setup Delete Command //sqlDa.DeleteCommand = cmbldr.GetDeleteCommand(); //Console.WriteLine("Delete Command: " + sqlDa.DeleteCommand.CommandText); //sqlDa.Update(empTable); DisplayRowStates("Row states for a freshly filled DataTable:", empTable); } } static void DisplayRowStates(string msg, DataTable table) { Console.WriteLine(msg); foreach (DataRow dr in table.Rows) { Console.WriteLine(dr[0].ToString() +":"+dr[1].ToString() +":"+dr.RowState.ToString()); } } } } Output: Update Command: UPDATE [Employees] SET [LastName] = @p1, [FirstName] = @p2, [Title] = @p3, [TitleOfCourtesy] = @p4, [BirthDate] = @p5, [HireDate] = @p6, [Address] = @p7, [City] = @p8, [Region] = @p9, [PostalCode] = @p10, [Country] = @p11, [HomePhone] = @p12, [Extension] = @p13, [Photo] = @p14, [Notes] = @p15, [ReportsTo] = @p16, [PhotoPath] = @p17 WHERE ( ([EmployeeID] = @p18) AND ([LastName] = @p19) AND ([FirstName] = @p20) AND ((@p21 = 1 AND [Title] IS NULL) OR ([Title] = @p22)) AND ((@p23 = 1 AND [TitleOfCourtesy] IS NULL) OR ([TitleOfCourtesy] = @p24)) AND ((@p25 = 1 AND [BirthDate] IS NULL) OR ([BirthDate] = @p26)) AND ((@p27 =1 AND [HireDate] IS NULL) OR ([HireDate] = @p28)) AND ((@p29 = 1 AND [Address] IS NULL) OR ([Address] = @p30)) AND ((@p31 = 1 AND [City] IS NULL) OR ([City] = @p32)) AND ((@p33 = 1 AND [Region] IS NULL) OR ([Region] = @p34)) AND ((@p35 = 1AND [PostalCode] IS NULL) OR ([PostalCode] = @p36)) AND ((@p37 = 1 AND [Country] IS NULL) OR ([Country] = @p38)) AND ((@p39 = 1 AND [HomePhone] IS NULL) OR ([HomePhone] = @p40)) AND ((@p41 = 1 AND [Extension] IS NULL) OR ([Extension] = @p42)) AND ((@p43 = 1 AND [ReportsTo] IS NULL) OR ([ReportsTo] = @p44)) AND ((@p45 = 1 AND [PhotoPath] IS NULL) OR ([PhotoPath] = @p46)) ) Insert Command: INSERT INTO [Employees] ( [LastName], [FirstName], [Title], [TitleOfCourtesy], [BirthDate], [HireDate], [Address], [City], [Region], [PostalCode], [Country], [HomePhone], [Extension], [Photo], [Notes], [ReportsTo], [PhotoPath] ) VALUES ( @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17 ) Row states for a finally filled DataTable: 1 : Mishra : Unchanged 2 : Fuller : Unchanged 3 : Leverling : Unchanged 4 : Peacock : Unchanged 5 : Buchanan : Unchanged 6 : Suyama : Unchanged 7 : King : Unchanged 8 : Callahan : Unchanged 9 : Dodsworth : Unchanged 100 : Sharma : Unchanged Press any key to continue . . .
जैसाकि इस Program के Output से हम समझ सकते हैं कि इस Program में सबसे पहले निम्नानुसार Statement द्वारा DataAdapter के UpdateCommand Property को Setup किया गया है:
// Setup Update Command sqlDa.UpdateCommand = cmbldr.GetUpdateCommand(); Console.WriteLine("Update Command: " + sqlDa.UpdateCommand.CommandText);
और फिर निम्नानुसार Statement द्वारा DataAdapter के InsertCommand Property को Setup किया गया है:
// Setup Insert Command sqlDa.InsertCommand = cmbldr.GetInsertCommand(); Console.WriteLine("Insert Command: " + sqlDa.InsertCommand.CommandText);
हालांकि इस Program में DeleteCommand को भी निम्नानुसार Setup किया गया है, लेकिन उसे Comment बनाया गया है, क्योंकि Employees Table एक Master Table है, जिससे Associated Detailed Table होने की वजह से Master Table के Record को Directly Delete नहीं किया जा सकता-
//Delete First Row //record = empTable.Rows[10]; //record.Delete(); . . . // Setup Delete Command //sqlDa.DeleteCommand = cmbldr.GetDeleteCommand(); //Console.WriteLine("Delete Command: " + sqlDa.DeleteCommand.CommandText); //sqlDa.Update(empTable);
परिणामस्वरूप जब उपरोक्त Code Execute हो जाता है, तो हमारा DataSet/DataTable Object फिर से Fresh Data से Filled हो जाता है। इसीलिए हम हमारे Output में देख सकते हैं कि सभी Rows की RowState Property में “Unchanged” मान Stored है, क्योंकि DataAdapter के माध्यम से Underlying Database में Permanent Changes Save होने के बाद Frontend में फिर से Refreshed Data से DataTable/DataSet Object Fill हो जाता है। यानी हमें Underlying Database में होने वाले Changed Data को Frontend में Disconnected Objects में Fill करने के लिए अलग से कोई Code लिखने की जरूरत नहीं होती।
हालांकि उपरोक्त Code Normal तरीके से काम करता है, लेकिन इस Code की एक बहुत बडी परेशानी है और वो ये है कि यदि हम उपरोक्तानुसार किसी DataTable के तीन Rows को क्रमश: Insert, Update व Delete करते हैं, तो हमारा DataAdapter Object, Underlying Database के साथ तीन बार Connection Open व Close करता है।
इस Issue को Resolve करने के लिए हम विभिन्न तरीके उपयोग में ले सकते हैं, जिनमें से एक तरीका ये है कि हम XML या Comma Separated String को सीधे ही Underlying Database के Stored Procedure में Pass करें। लेकिन इस तरीके के स्थान पर हम एक और तरीका Use कर सकते हैं, जिसके अन्तर्गत हम SqlDataAdapter Object की UpdateBatchSize Property को Use कर सकते हैं और इस Property को हमें Update Statement से Just पहले निम्नानुसार तरीके से Set करना होता है:
sqlDa.UpdateBatchSize = 3;
जब हम इस तरह से UpdateBatchSize Property को Set करते हैं, तब भी हमें प्राप्त होने वाले Output में किसी प्रकार का कोई परिवर्तन दिखाई नहीं पडता। लेकिन इस Property को Set करने पर यदि किसी DataTable Object में तीन Rows पर Insert, Update व Delete Commands Execute करने हों, तो ये तीनों काम Underlying Database पर एक ही बार Connection Open व Close करके पूरा कर दिया जाता है, जिससे हमारे Application की Performance तीन गुना बेहतर हो जाती है। क्योंकि Network के माध्यम से Frontend व Backend के बीच Data का Transfer केवल एक ही बार होता है।
DataAdapter को उपयोग में लेने का एक सबसे बडा Downside ये है कि ये किसी भी Single Row को एक Individual Entity के रूप में Treat करता है और हर Row के Modification (Insert, Update, Delete) के लिए SQL Command को Execute करने के लिए बाध्य करता है।
SqlBulkCopy Class
हालांकि UpdateBatchSize Property Set करके हम Network Roundtrip को Reduce कर सकते हैं, लेकिन जब Multiple Database पर Stored Data के साथ Operate करना होता है, तब UpdateBatchSize Property को Use करने का ये तरीका भी Database की Performance को कोई विशेष फायदा नहीं पहुंचाता। इसलिए .NET Framework में इस स्थिति को ज्यादा बेहतर तरीके से Handle करने के लिए SqlBulkCopy नाम की एक Class को Add किया गया है।
SqlBulkCopy Class दो अलग Open SqlConnections के माध्यम से एक Table के Data को Directly दूसरे Table में Copy करने का काम करता है। दोनों Open SqlConnections समान Underlying Database को Point कर सकते हैं अथवा किसी अन्य Database को भी Point कर सकते हैं। इसे समझने के लिए हम निम्नानुसार एक Console Application Create कर सकते हैं:
using System; using System.Data; using System.Data.SqlClient; namespace StateManagement { class Program { static void Main(string[] args) { string connectionString="Data Source=.\\SQLSERVEREXPRESS;Initial Catalog=Northwind;Integrated Security=True"; using (SqlConnection firstConnection = new SqlConnection(connectionString)) { SqlCommand testCommand = firstConnection.CreateCommand(); testCommand.CommandText = "SELECT * FROM Employees"; firstConnection.Open(); SqlDataReader dr = testCommand.ExecuteReader(); using (SqlConnection secondConnection = new SqlConnection(connectionString)) { SqlBulkCopy bc = new SqlBulkCopy(secondConnection); bc.DestinationTableName = "EmployeesCopy"; bc.WriteToServer(dr); bc.Close(); dr.Close(); } //Dispose() Called on secondConnection } //Dispose() Called on firstConnection } } }
इस Program में सबसे पहले हमने निम्न Statement द्वारा firstConnection नाम का एक SqlConnection Object Create किया है:
using (SqlConnection firstConnection = new SqlConnection(connectionString))
और Connection Object Create होने के बाद testCommand नाम का एक Command Object Create किया है, जिसकी CommandText Property को निम्नानुसार Set किया है:
SqlCommand testCommand = firstConnection.CreateCommand();
testCommand.CommandText = “SELECT * FROM Employees”;
अन्त में firstConnection को निम्नानुसार Statement द्वारा Open() Method का प्रयोग करते हुए Underlying DataSource से Connect किया है:
SqlDataReader dr = testCommand.ExecuteReader();
फिर निम्न Statement द्वारा secondConnection नाम का एक और Connection Object Create किया है:
using (SqlConnection secondConnection = new SqlConnection(connectionString))
चूंकि हम दोनों ही Connections को समान Underlying DataSource पर Open कर रहे हैं, इसलिए दोनों ही Connection Objects Create करने के लिए हमने समान connectionString का प्रयोग किया है। इस Statement के Execute होने तक Create होने वाले दोनों Connection Objects समान Underlying DataSource से ही Connected हैं। फिर निम्न Statement Execute होता है:
SqlBulkCopy bc = new SqlBulkCopy(secondConnection);
ये Statement secondConnection Object के लिए एक SqlBulkCopy Object Create करता है और निम्न Statement के माध्यम से DestinationTableName Property में उस Table के नाम को Specify करता है, जिसमें Copy होने वाले Data को Finally Store करना है:
bc.DestinationTableName = “EmployeesCopy”;
फिर निम्न Statement Execute होता है:
bc.WriteToServer(dr);
ये Statement SqlBulkCopy Object के DestinationTableName Property में Specified Table में firstConnection के माध्यम से Read किए गए Data को, जो कि dr नाम के DataReader Object में Stored है, Write कर देता है। परिणामस्वरूप Employees नाम की Table में जितने भी Records होते हैं, वे सभी एक ही बार में EmployeesCopy नाम की Destination Table में Store हो जाते हैं।
यहां मुख्य रूप से ध्यान देने वाली बात यही है कि Employees व EmployeesCopy नाम की दोनों Tables का Structure एक समान होना जरूरी है। यदि दोनों Tables का Structure एक समान न हो, तो SqlBulkCopy Object, Source Table के Data को Destination Table में Copy नहीं कर सकता। जबकि समान Structure का Table Create करने के लिए SQL Server, MySQL या Oracle जैसे किसी भी Database Software पर हम निम्नानुसार SQL Query Fire कर सकते हैं:
CREATE TABLE EmployeesCopy AS SELECT * FROM Employees WHERE 1 = 2
ये SQL Statement Employees Table के समान Structure का एक नया Table समान Schema में Create करेगा, लेकिन Employees Table का कोई भी Data EmployeesCopy Table में Store नहीं होगा, क्योंकि हमने WHERE Clause के बाद जो Condition 1 = 2 Specify की है, वह कभी भी TRUE नहीं होगी।
ये Article इस वेबसाईट पर Selling हेतु उपलब्ध EBook ADO.NET with C# in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी।
ADO.NET with C# in Hindi | Page:501 | Format: PDF