Since the release of our first ADO.NET data providers, Progress DataDirect has been offering secure, reliable, and high-performance connectivity solutions to enterprise data sources, such as Microsoft SQL Server.
To reduce application development time, this tutorial provides working C# code examples for typical database access tasks using the DataDirect for ADO.NET SQL Server data provider.
using System.Data;using DDTek.SQLServer;This tutorial contains sample code for the following tasks:
DataDirect Connect offers ADO.NET managed code data providers for Db2, Oracle, Sybase, and SQL Server.
Many of the samples in this tutorial use the emp and dept tables. You can create these tables using an ISQL script or the data provider. The following sections provide examples for both of these methods.
ISQL is a command-line interface for Microsoft SQL Server. The following script can be run in ISQL to create the emp and dept tables. Refer to the Microsoft SQL Server documentation for details.
CREATE TABLE emp (empno INT PRIMARY KEY,ename VARCHAR(10),job VARCHAR(9),mgr INT NULL,hiredate DATETIME,sal NUMERIC(7,2),comm NUMERIC(7,2) NULL,dept INT)begininsert into emp values (1,'JOHNSON','ADMIN',6,'12-17-1990',18000,NULL,4)insert into emp values (2,'HARDING','MANAGER',9,'02-02-1998',52000,300,3)insert into emp values (3,'TAFT','SALES I',2,'01-02-1996',25000,500,3)insert into emp values (4,'HOOVER','SALES I',2,'04-02-1990',27000,NULL,3)insert into emp values (5,'LINCOLN','TECH',6,'06-23-1994',22500,1400,4)insert into emp values (6,'GARFIELD','MANAGER',9,'05-01-1993',54000,NULL,4)insert into emp values (7,'POLK','TECH',6,'09-22-1997',25000,NULL,4)insert into emp values (8,'GRANT','ENGINEER',10,'03-30-1997',32000,NULL,2)insert into emp values (9,'JACKSON','CEO',NULL,'01-01-1990',75000,NULL,4)insert into emp values (10,'FILLMORE','MANAGER',9,'08-09-1994',56000,NULL,2)insert into emp values (11,'ADAMS','ENGINEER',10,'03-15-1996',34000,NULL,2)insert into emp values (12,'WASHINGTON','ADMIN',6,'04-16-1998',18000,NULL,4)insert into emp values (13,'MONROE','ENGINEER',10,'12-03-2000',30000,NULL,2)insert into emp values (14,'ROOSEVELT','CPA',9,'10-12-1995',35000,NULL,1)endCREATE TABLE dept (deptno INT NOT NULL,dname VARCHAR(14),loc VARCHAR(13))begininsert into dept values (1,'ACCOUNTING','ST LOUIS')insert into dept values (2,'RESEARCH','NEW YORK')insert into dept values (3,'SALES','ATLANTA')insert into dept values (4, 'OPERATIONS','SEATTLE')end
The sample tables used in this Product Brief can be created with the data provider, as shown in the following code example:
SQLServerConnection Conn;Conn = new SQLServerConnection("host=nc-star;port=1433;User ID=test01;Password=test01; Database Name=Test");try{Conn.Open();}catch (SQLServerException ex){// Connection failedConsole.WriteLine(ex.Message);return;}string[] DropTableSQL = {"drop table emp", "drop table dept"};for (int x=0; x<=1; x++){try{// Drop the tables, don't care if they don't existSQLServerCommand DBCmd = new SQLServerCommand(DropTableSQL[x], Conn);DBCmd.ExecuteNonQuery();}catch (SQLServerException ex){}// Create the tablesstring CreateEmpTableSQL = "CREATE TABLE emp(empno INT PRIMARY KEY NOT NULL,"+"ename VARCHAR(10) NOT NULL,"+"job VARCHAR(9) NOT NULL,"+"mgr INT,"+"hiredate DATETIME NOT NULL,"+"sal NUMERIC(7,2) NOT NULL,"+"comm NUMERIC(7,2),"+"dept INT NOT NULL)";string CreateDeptTableSQL = "CREATE TABLE dept ("+"deptno INT NOT NULL,"+"dname VARCHAR(14),"+"loc VARCHAR(13))";try{SQLServerCommand DBCmd = new SQLServerCommand(CreateEmpTableSQL, Conn);DBCmd.ExecuteNonQuery();DBCmd.CommandText = CreateDeptTableSQL;DBCmd.ExecuteNonQuery();}catch (Exception ex){//Create tables failedConsole.WriteLine (ex.Message);return;}// Now insert the recordsstring[] InsertEmpRecordsSQL = { "insert into emp values (1,'JOHNSON','ADMIN',6,'12-17-1990',18000,NULL,4)", "insert into emp values (2,'HARDING','MANAGER',9,'02-02-1998',52000,300,3)", "insert into emp values (3,'TAFT','SALES I',2,'01-02-1996',25000,500,3)", "insert into emp values (4,'HOOVER','SALES I',2,'04-02-1990',27000,NULL,3)", "insert into emp values (5,'LINCOLN','TECH',6,'06-23-1994',22500,1400,4)", "insert into emp values (6,'GARFIELD','MANAGER',9,'05-01-1993',54000,NULL,4)", "insert into emp values (7,'POLK','TECH',6,'09-22-1997',25000,NULL,4)", "insert into emp values (8,'GRANT','ENGINEER',10,'03-30-1997',32000,NULL,2)", "insert into emp values (9,'JACKSON','CEO',NULL,'01-01-1990',75000,NULL,4)","insert into emp values (10,'FILLMORE','MANAGER',9,'08-09-1994',56000, NULL,2)", "insert into emp values (11,'ADAMS','ENGINEER',10,'03-15-1996',34000, NULL,2)", "insert into emp values (12,'WASHINGTON','ADMIN',6,'04-16-1998',18000,NULL,4)", "insert into emp values (13,'MONROE','ENGINEER',10,'12-03-2000',30000,NULL,2)", "insert into emp values (14,'ROOSEVELT','CPA',9,'10-12-1995',35000,NULL,1)"};string[] InsertDeptRecordsSQL = { "insert into dept values (1,'ACCOUNTING','ST LOUIS')", "insert into dept values (2,'RESEARCH','NEW YORK')", "insert into dept values (3,'SALES','ATLANTA')", "insert into dept values (4, 'OPERATIONS','SEATTLE')"};// Insert dept table records firstfor (int x = 0; x<InsertDeptRecordsSQL.Length; x++){try{SQLServerCommand DBCmd = new SQLServerCommand(InsertDeptRecordsSQL[x], Conn);DBCmd.ExecuteNonQuery();}catch (Exception ex){Console.WriteLine (ex.Message);return;}}// Now the emp table recordsfor (int x = 0; x<InsertEmpRecordsSQL.Length; x++){try{SQLServerCommand DBCmd = new SQLServerCommand(InsertEmpRecordsSQL[x], Conn);DBCmd.ExecuteNonQuery();}catch (Exception ex){Console.WriteLine (ex.Message);return;}}Console.WriteLine ("Tables created Successfully!");// Close the connectionConn.Close();
The DataReader provides the fastest, but least flexible way to retrieve data from the database. When using DataReader, data is returned one record at a time as a read-only, forward-only stream of data. Using DataReader is the preferred method if you need to retrieve a large number of records quickly. Alternatively, the DataSet object provides a more flexible method to return results; however, it offers slower performance and requires large amounts of data to hold the results.
The following code example executes a simple query against the emp table in a Microsoft SQL Server database and reads the results using a DataReader.
Open connection to SQL Server databaseSQLServerConnection Conn;try{Conn = new SQLServerConnection("host=nc-star;port=1433;User ID=test01;Password=test01; Database Name=Test");Conn.Open();Console.WriteLine ("Connection successful!");}catch (Exception ex){// Connection failedConsole.WriteLine(ex.Message);return;}try{// Create a SQL commandstring strSQL = "SELECT ename FROM emp WHERE sal>50000";SQLServerCommand DBCmd = new SQLServerCommand(strSQL, Conn);SQLServerDataReader myDataReader;myDataReader = DBCmd.ExecuteReader();while (myDataReader.Read()){Console.WriteLine("High salaries: " + myDataReader["ename"].ToString());}myDataReader.Close();// Close the connectionConn.Close();}catch (Exception ex){Console.WriteLine(ex.Message);return;}
The following code example demonstrates how to execute local transactions using the emp table:
SQLServerConnection Conn;Conn = new SQLServerConnection("host=nc-star;port=1433; User ID=test01;Password=test01;Database Name=Test");try{Conn.Open();Console.WriteLine ("Connection successful!");}catch (Exception ex){// Connection failedConsole.WriteLine(ex.Message);return;}SQLServerCommand DBCmd = new SQLServerCommand();SQLServerTransaction DBTxn = null;try{DBTxn = Conn.BeginTransaction();// Set the Connection property of the Command objectDBCmd.Connection = Conn;// Set the text of the Command to the INSERT statementDBCmd.CommandText = "insert into emp VALUES(16,'HAYES','ADMIN',6,'17-APR-2002',18000,NULL,4)";// Set the transaction property of the Command objectDBCmd.Transaction = DBTxn;// Execute the statement with ExecuteNonQuery, because we are not// returning resultsDBCmd.ExecuteNonQuery();// Now commit the transactionDBTxn.Commit();// Display any exceptionsConsole.WriteLine ("Transaction Committed!");}catch (Exception ex){// Display any exceptionsConsole.WriteLine (ex.Message);// If anything failed after the connection was opened, roll back the// transactionif (DBTxn != null){DBTxn.Rollback();}}// Close the connectionConn.Close();
The following code shows how to use a distributed transaction across two connections to two different Microsoft SQL Server servers. The following example uses the emp table.
NOTE:
When you use distributed transactions, you must add System.EnterpriseServices to the Solution Reference list. In addition, the application must be strongly named.
To use a distributed transaction across two connections to two different servers:
sn –k SolutionName.snkAssemblyInfo.cs file from the Solution.using System;using System.EnterpriseServices;using System.Reflection;using DDTek.SQLServer;[assembly: ApplicationName("yourapplicationname")][assembly: AssemblyKeyFileAttribute(@"..\..\yourapplicationname.snk")]namespace DistTransaction{/// <summary>/// Summary description for Class1./// </summary>public class Class1{/// <summary>/// The main entry point for the application./// </summary>[STAThread]static void Main(string[] args){SQLServerConnection Conn1;Conn1 = new SQLServerConnection("host=nc-star;port=1433;User ID=test01;Password=test01;Database Name=Test;Enlist=true");SQLServerConnection Conn2;Conn2 = new SQLServerConnection("host=nc-star;port=1433;User ID=test07;Password= test07;Database Name=test;Enlist=true");try{DistributedTran myDistributedTran = new DistributedTran();myDistributedTran.TestDistributedTransaction(Conn1, Conn2);Console.WriteLine("Success!!");}catch (Exception e){System.Console.WriteLine("Error returned: " + e.Message);}}}/// <summary>/// To use distributed transactions in .NET, we need a ServicedComponent/// derived class with transaction attribute declared as "Required"./// </summary>[Transaction(TransactionOption.Required) ]public class DistributedTran : ServicedComponent{/// <summary>/// This method executes two SQL statements./// If both are successful, both are committed by DTC after the/// method finishes. However, if an exception is thrown, both will be/// rolled back by DTC./// </summary>[AutoComplete]public void TestDistributedTransaction(SQLServerConnection Conn1,SQLServerConnection Conn2){// The following Insert statement goes to the first server, orca.// This Insert statement does not produce any errors.string DBCmdSql1 = "Insert into emp VALUES(16,'HAYES','ADMIN',6,'17-NOV-2002',18000,NULL,4)";string DBCmdSql2 = "Delete from emp WHERE sal > 100000";try{Conn1.Open();Conn2.Open();Console.WriteLine ("Connection successful!");}catch (Exception ex){// Connection failedConsole.WriteLine(ex.Message);return;}SQLServerCommand DBCmd1 = new SQLServerCommand(DBCmdSql1, Conn1);SQLServerCommand DBCmd2 = new SQLServerCommand(DBCmdSql2, Conn2);DBCmd1.ExecuteNonQuery();DBCmd2.ExecuteNonQuery();Conn1.Close();Conn2.Close();Console.WriteLine("Success!! ");}}}A CommandBuilder object can be used to generate the Insert, Update, and Delete statements for a DataAdapter.
The following code example uses the emp table with the CommandBuilder to update a DataSet:
SQLServerConnection Conn;Conn = new SQLServerConnection("host=nc-star; port=4100;User ID=test01;Password=test01;Database Name=Test ");try{Conn.Open();Console.WriteLine ("Connection successful!");}catch (Exception ex){// Connection failedConsole.WriteLine(ex.Message);return;}SQLServerDataAdapter myDataAdapter = new SQLServerDataAdapter();SQLServerCommand DBCmd = new SQLServerCommand("select * from emp",Conn);myDataAdapter.SelectCommand = DBCmd;// Set up the CommandBuilderSQLServerCommandBuilder CommBuild = new SQLServerCommandBuilder(myDataAdapter);DataSet myDataSet = new DataSet();try{myDataAdapter.Fill(myDataSet);// Now change the salary of the first employeeDataRow myRow;myRow = myDataSet.Tables["Table"].Rows[0];myRow["sal"] = 95000;// Tell the DataAdapter to resync with the SQL Server server.// Without the CommandBuilder, this line would fail.myDataAdapter.Update(myDataSet);Console.WriteLine ("Update with CommandBuilder Successful!");}catch (Exception ex){// Display any exceptionsConsole.WriteLine (ex.Message);}// Close the connectionConn.Close();
When updating a row in the data source, the DataSet uses the SQL provided in UpdateCommand of the Data Adapter. The Update statement can use parameters that contain a unique identifier, such as the primary key, and the columns to be updated, as shown in the following example:
[C#]string updateSQL As String = "UPDATE emp SET sal = ?, job = ? + = WHERE empno = ?;
The parameterized query statements define the parameters that to be created. Refer to the DataDirect Connect for ADO.NET User's Guide for more information about using parameters with the SQL Server data provider.
The following code example shows how to use an UpdateCommand to synchronize changes made to a DataSet with data on the emp table. To accomplish this, the code:
SQLServerConnection Conn =new SQLServerConnection("host=nc-star;port=4100;User ID=test01; Password=test01;Database Name=Test");try{string selectText = "select sal, job, empno from emp";string updateText = "update emp set sal = ?, job = ? where empno = ?";SQLServerDataAdapter adapter = new SQLServerDataAdapter(selectText, Conn);SQLServerCommand updateCommand = new SQLServerCommand(updateText, Conn);adapter.UpdateCommand = updateCommand;updateCommand.Parameters.Add("@sal", SQLServerDbType.Int, 15, "SAL");updateCommand.Parameters.Add("@job", SQLServerDbType.VarChar, 9, "JOB");updateCommand.Parameters.Add("@empno", SQLServerDbType.Int, 15, "empno");DataSet myDataSet = new DataSet("emp");adapter.Fill(myDataSet, "emp");// Give employee number 11 a promotion and a raiseDataRow changeRow = myDataSet.Tables["emp"].Rows[11];changeRow["sal"] = "35000";changeRow["job"] = "MANAGER";// Send back to databaseadapter.Update(myDataSet, "emp");myDataSet.Dispose();}catch (Exception ex){// Display any exceptionsConsole.WriteLine (ex.Message);}Console.WriteLine("DataSet Updated Successfully!");// Close the connectionConn.Close();
Stored procedures are called using a Command object. When you issue a command on a stored procedure, you must set the CommandType of the Command object to StoredProcedure, or use the ODBC/JDBC escape syntax. For information on using the ODBC/JDBC escape syntax with the data provider, refer to the DataDirect Connect for ADO.NET User's Guide.
The following code examples demonstrate how to create and execute a stored procedure on a SQL Server database and read the results using a DataReader. The sample data used in these examples is in the emp table.
The following code creates the stored procedure:
// Open connection to SQL Server databaseSQLServerConnection Conn;Conn = new SQLServerConnection("host=nc-star;port=4100;User ID=test01;Password=test01;Database Name=Test");try{Conn.Open();Console.WriteLine ("Connection successful!");}catch (Exception ex){// Connection failedConsole.WriteLine(ex.Message);return;}string spCreate = "CREATE PROCEDURE GetEmpSalary(@empno int,@salnumeric(7,2) output)AS SELECT @sal = sal from emp where empno = @empno";try{SQLServerCommand DBCmd=new SQLServerCommand(spCreate, Conn);DBCmd.ExecuteNonQuery();}catch (Exception ex){//Create procedure failedConsole.WriteLine (ex.Message);return;}Console.WriteLine ("Procedure Created Successfully!");
The following code example executes the GetEmpSalary stored procedure:
// Open connection to SQL Server databaseSQLServerConnection Conn;try{Conn = new SQLServerConnection("host=nc-star;port=4100;User ID=test01;Password=test01;Database Name=Test");Conn.Open();Console.WriteLine ("Connection successful!");}catch (Exception ex){// Connection failedConsole.WriteLine(ex.Message);return;}// Make a command object for the stored procedure// You must set the CommandType of the Command object// to StoredProcedureSQLServerCommand DBCmd = new SQLServerCommand("GetEmpSalary",Conn);DBCmd.CommandType = CommandType.StoredProcedure;// The stored procedure expects one input and one output parameter// Define the parameters for the stored procedure// We don't need to specify the direction of the parameter, since thedefault is INPUTDBCmd.Parameters.Add("@empno", SQLServerDbType.Int, 10).Value = 5;// Output parameterDBCmd.Parameters.Add("@sal", SQLServerDbType.Numeric, 10).Direction =ParameterDirection.Output;SQLServerDataReader myDataReader;try{myDataReader = DBCmd.ExecuteReader();myDataReader.Close();}catch (Exception ex){// Display any exceptionsConsole.WriteLine (ex.Message);}Console.WriteLine("Procedure Executed Successfully!");// Close the connectionConn.Close();
You can use the ExecuteScalar method of the Command object to return a single value, such as a sum or a count, from the database. The ExecuteScalar method returns the value of the first column of the first row of the result set. If the result set has only one row and one column, you can use this method to speed up retrieval of the value.
The following code example retrieves the number of employees who make more than $50,000 from the emp table.
// Open connection to SQL Server databaseSQLServerConnection Conn;Conn = new SQLServerConnection("host=nc-star;port=4100;User ID=test01;Password=test01;Database Name=Test");try{Conn.Open();Console.WriteLine ("Connection successful!");}catch (Exception ex){// Connection failedConsole.WriteLine(ex.Message);return;}// Make a command objectSQLServerCommand salCmd = new SQLServerCommand("select count(sal) from empwhere sal>50000",Conn);try{int count = (int)salCmd.ExecuteScalar();Console.WriteLine("Count of Salaries >$50,000 : "+ Convert.ToString(count));}catch (Exception ex){// Display any exceptionsConsole.WriteLine(ex.Message);}// Close the connectionConn.Close();
The data provider handles database server warnings through the InfoMessage delegates on the Connection objects.
The following example shows how to retrieve a warning generated by a Microsoft SQL Server server:
// Define an event handlerpublic void myHandler(object sender, SQLServerInfoMessageEventArgs e){// Display any warningsConsole.WriteLine ("Warning Returned: " + e.Message);}Add the following code to a method and call it:SQLServerConnection Conn;Conn = new SQLServerConnection("host=nc-star;port=4100;User ID=test01;Password=test01;Database Name=Test");SQLServerCommand DBCmd = new SQLServerCommand("print 'This is a Warning.'",Conn);SQLServerDataReader myDataReader;try{Conn.InfoMessage += new SQLServerInfoMessageEventHandler(myHandler);Conn.Open();myDataReader = DBCmd.ExecuteReader();// This will throw a SQLServerInfoMessageEvent as the print// statement generates a warning.}catch (Exception ex){// Display any exceptions in a messageboxMessageBox.Show (ex.Message);}// Close the connectionConn.Close();Progress DataDirect provides fast and functional ADO.NET managed data providers, so that you can develop your .NET solution with unrivaled performance.
The code examples we discussed in this tutorial, which provide working C# code for typical data access tasks, can help you to get started quickly and reduce your development effort when using the DataDirect Connect for ADO.NET SQL Server data provider with your ADO.NET application.
DataDirect Connect offers ADO.NET managed code data providers for Db2, Oracle, Sybase, and SQL Server.