Thursday, January 21, 2010

SADataAdapter .net (source SQL Anywhere)

The SADataAdapter retrieves the result set into a DataSet. A DataSet is a collection of tables and the relationships and constraints between those tables. The DataSet is built into the .NET Framework, and is independent of the Data Provider used to connect to your database.

When you use the SADataAdapter, you must be connected to the database to fill the DataSet and to update the database with changes made to the DataSet. However, once the DataSet is filled, you can modify the DataSet while disconnected from the database.

If you do not want to apply your changes to the database right away, you can write the DataSet, including the data and/or the schema, to an XML file using the WriteXML method. Then, you can apply the changes at a later time by loading a DataSet with the ReadXML method.

For more information, see the .NET Framework documentation for WriteXML and ReadXML.

When you call the Update method to apply changes from the DataSet to the database, the SADataAdapter analyzes the changes that have been made and then invokes the appropriate commands, INSERT, UPDATE, or DELETE, as necessary. When you use the DataSet, you can only make changes (inserts, updates, or deletes) to data that is from a single table. You cannot update result sets that are based on joins. If another user has a lock on the row you are trying to update, an exception is thrown.

Caution
Any changes you make to the DataSet are made while you are disconnected. This means that your application does not have locks on these rows in the database. Your application must be designed to resolve any conflicts that may occur when changes from the DataSet are applied to the database in the event that another user changes the data you are modifying before your changes are applied to the database.


Resolving conflicts when using the SADataAdapter
When you use the SADataAdapter, no locks are placed on the rows in the database. This means there is the potential for conflicts to arise when you apply changes from the DataSet to the database. Your application should include logic to resolve or log conflicts that arise.

Some of the conflicts that your application logic should address include:

Unique primary keys If two users insert new rows into a table, each row must have a unique primary key. For tables with autoincrement primary keys, the values in the DataSet may become out of sync with the values in the data source.

For information about obtaining primary key values for autoincrement primary keys, see Obtaining primary key values.

Updates made to the same value If two users modify the same value, your application should include logic to determine which value is correct.

Schema changes If a user modifies the schema of a table you have updated in the DataSet, the update will fail when you apply the changes to the database.

Data concurrency Concurrent applications should see a consistent set of data. The SADataAdapter does not place a lock on rows that it fetches, so another user can update a value in the database once you have retrieved the DataSet and are working offline.

Many of these potential problems can be avoided by using the SACommand, SADataReader, and SATransaction objects to apply changes to the database. The SATransaction object is recommended because it allows you to set the isolation level for the transaction and it places locks on the rows so that other users cannot modify them.

For more information about using transactions to apply your changes to the database, see Inserting, updating, and deleting rows using the SACommand object.

To simplify the process of conflict resolution, you can design your INSERT, UPDATE, or DELETE statement to be a stored procedure call. By including INSERT, UPDATE, and DELETE statements in stored procedures, you can catch the error if the operation fails. In addition to the statement, you can add error handling logic to the stored procedure so that if the operation fails the appropriate action is taken, such as recording the error to a log file, or trying the operation again.

To insert rows into a table using the SADataAdapter
Declare and initialize an SAConnection object.

SAConnection conn = new SAConnection(
c_connStr );Open the connection.

conn.Open();Create a new SADataAdapter object.

SADataAdapter adapter = new SADataAdapter();
adapter.MissingMappingAction =
MissingMappingAction.Passthrough;
adapter.MissingSchemaAction =
MissingSchemaAction.Add;Create the necessary SACommand objects and define any necessary parameters.

The following code creates a SELECT and an INSERT command and defines the parameters for the INSERT command.

adapter.SelectCommand = new SACommand(
"SELECT * FROM Departments", conn );
adapter.InsertCommand = new SACommand(
"INSERT INTO Departments( DepartmentID, DepartmentName )
VALUES( ?, ? )", conn );
adapter.InsertCommand.UpdatedRowSource =
UpdateRowSource.None;
SAParameter parm = new SAParameter();
parm.SADbType = SADbType.Integer;
parm.SourceColumn = "DepartmentID";
parm.SourceVersion = DataRowVersion.Current;
adapter.InsertCommand.Parameters.Add(
parm );
parm = new SAParameter();
parm.SADbType = SADbType.Char;
parm.SourceColumn = "DepartmentName";
parm.SourceVersion = DataRowVersion.Current;
adapter.InsertCommand.Parameters.Add( parm );Fill the DataTable with the results of the SELECT statement.

DataTable dataTable = new DataTable( "Departments" );
int rowCount = adapter.Fill( dataTable );Insert the new rows into the DataTable and apply the changes to the database.

DataRow row1 = dataTable.NewRow();
row1[0] = 600;
row1[1] = "Eastern Sales";
dataTable.Rows.Add( row1 );
DataRow row2 = dataTable.NewRow();
row2[0] = 700;
row2[1] = "Western Sales";
dataTable.Rows.Add( row2 );
recordsAffected = adapter.Update( dataTable );Display the results of the updates.

dataTable.Clear();
rowCount = adapter.Fill( dataTable );
dataGrid.DataSource = dataTable;Close the connection.

conn.Close();To update rows using the SADataAdapter object
Declare and initialize an SAConnection object.

SAConnection conn = new SAConnection( c_connStr );Open the connection.

conn.Open();Create a new SADataAdapter object.

SADataAdapter adapter = new SADataAdapter();
adapter.MissingMappingAction =
MissingMappingAction.Passthrough;
adapter.MissingSchemaAction =
MissingSchemaAction.Add;Create an SACommand object and define its parameters.

The following code creates a SELECT and an UPDATE command and defines the parameters for the UPDATE command.

adapter.SelectCommand = new SACommand(
"SELECT * FROM Departments WHERE DepartmentID > 500",
conn );
adapter.UpdateCommand = new SACommand(
"UPDATE Departments SET DepartmentName = ?
WHERE DepartmentID = ?", conn );
adapter.UpdateCommand.UpdatedRowSource =
UpdateRowSource.None;
SAParameter parm = new SAParameter();
parm.SADbType = SADbType.Char;
parm.SourceColumn = "DepartmentName";
parm.SourceVersion = DataRowVersion.Current;
adapter.UpdateCommand.Parameters.Add( parm );
parm = new SAParameter();
parm.SADbType = SADbType.Integer;
parm.SourceColumn = "DepartmentID";
parm.SourceVersion = DataRowVersion.Original;
adapter.UpdateCommand.Parameters.Add( parm );Fill the DataTable with the results of the SELECT statement.

DataTable dataTable = new DataTable( "Departments" );
int rowCount = adapter.Fill( dataTable );Update the DataTable with the updated values for the rows and apply the changes to the database.

foreach ( DataRow row in dataTable.Rows )
{
row[1] = ( string ) row[1] + "_Updated";
}
recordsAffected = adapter.Update( dataTable );Bind the results to the grid on the screen.

dataTable.Clear();
adapter.SelectCommand.CommandText =
"SELECT * FROM Departments";
rowCount = adapter.Fill( dataTable );
dataGrid.DataSource = dataTable;Close the connection.

conn.Close();To delete rows from a table using the SADataAdapter object
Declare and initialize an SAConnection object.

SAConnection conn = new SAConnection( c_connStr );Open the connection.

conn.Open();Create an SADataAdapter object.

SADataAdapter adapter = new SADataAdapter();
adapter.MissingMappingAction =
MissingMappingAction.Passthrough;
adapter.MissingSchemaAction =
MissingSchemaAction.AddWithKey;Create the required SACommand objects and define any necessary parameters.

The following code creates a SELECT and a DELETE command and defines the parameters for the DELETE command.

adapter.SelectCommand = new SACommand(
"SELECT * FROM Departments WHERE DepartmentID > 500",
conn );
adapter.DeleteCommand = new SACommand(
"DELETE FROM Departments WHERE DepartmentID = ?",
conn );
adapter.DeleteCommand.UpdatedRowSource =
UpdateRowSource.None;
SAParameter parm = new SAParameter();
parm.SADbType = SADbType.Integer;
parm.SourceColumn = "DepartmentID";
parm.SourceVersion = DataRowVersion.Original;
adapter.DeleteCommand.Parameters.Add( parm );Fill the DataTable with the results of the SELECT statement.

DataTable dataTable = new DataTable( "Departments" );
int rowCount = adapter.Fill( dataTable );Modify the DataTable and apply the changes to the database.

for each ( DataRow in dataTable.Rows )
{
row.Delete();
}
recordsAffected = adapter.Update( dataTable )Bind the results to the grid on the screen.

dataTable.Clear();
rowCount = adapter.Fill( dataTable );
dataGrid.DataSource = dataTable;Close the connection.

conn.Close();

JDBC

JDBC
The Java Database Connectivity API (JDBC) is used to connect Java programs with databases.

The API provides for a call level API for SQL based database access. It allows you to establish a connection with a database, send SQL statements, and process the results.

The JDBC API consists of two major sets of interfaces; the first is for application writers and the second is the JDBC driver for driver writers.

The connection to the database can be through direct connections to the database, through client libraries, or through JDBC-ODBC bridges.

The bridge connection is typically used for a device that does not have client libraries or native connections supported.

The different Oracle JDBC drivers are

Thin - pure Java driver used on the client side that does not need an Oracle client installation. It is recommended that you use this driver unless you need support for non-TCP/IP networks because it provides for maximum portability and performance.
Oracle Call Interface driver (OCI). This uses the Oracle client installation libraries and interfaces. If you want to support connection pooling or client side caching of requests, use this driver. You will also need this driver if you are using transparent application failover (TAF) from your application as well as strong authentication like Kerberos and PKI certificates.
JDBC-ODBC bridge. This uses the ODBC driver in Windows to connect to the database

The JDBC drivers that come with the 10gR2 Client and server are compatible with JDK 1.2.x and later. The JDK 1.0.x and 1.1.x are no longer supported.

A sample code segment for connecting to a database from Java looks like:


String url = "jdbc:odbc:mydatabase";
Connection con = DriverManager.getConnection(url, "userID", "password");
if (con) {
System.out.println(" connection good");
} else {
System.out.println(" connection failed");
}


In this example we use the ODBC-JDBC bridge to connect to the database using the ODBC data source named mydatabase.

We could have used "jdbc:dbnet://mydatabase.oracle.com:1521/mydatabase" to connect directly to the listener.

We could also add attributes to the ODBC connection to define things like CacheSize, AlternatServer, or connection timeout.

To create a failover or load balance definition for a JDBC connection you can do this with the following url definitions


String url = "jdbc:inetora:localhost:1521:mydatabase?failover=true&host1 =standbyDB.oracle.com&port1=1521&host2=remoteDB.oracle.com&port2=1521"; String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
(HOST=example.com)(PORT=1521))
(ADDRESS=(PROTOCOL=TCP)
(HOST=failover.example.com)(PORT=1521))
(FAILOVER=true)(LOAD_BALANCE=false)
(CONNECT_DATA=(SERVER=DEDICATED)(SID=foo)))";