Side-by-Side Execution and ADO.NET

Side-by-side execution in the .NET Framework is the ability to execute an application on a single computer that has multiple versions of the .NET Framework installed, without that application being affected. That is, even though there are multiple versions of the .NET Framework available on a single computer, the application uses the version that it was compiled for and is unaffected by the other .NET Framework versions installed on the computer. For detailed information on configuring side-by-side execution, see Side-by-Side Execution.

It is possible for an application compiled using one version of the .NET Framework to run on a different version of the .NET Framework. However, it is recommended that you compile a version of the application for each version of the .NET Framework installed and run them separately. In either scenario, you should be aware of changes in ADO.NET between releases that can affect the forward or backward compatibility of your application.

Forward and Backward Compatibility

Forward compatibility means that an application can be compiled and run on both later and earlier versions of the .NET Framework. ADO.NET code, written for the .NET Framework version 1.1, is forward compatible provided you are not using new features introduced in the .NET Framework version 1.1. The new features added to the ADO.NET in the .NET Framework version 1.1 are:

Backward compatibility means that an application is compiled for an earlier version of the .NET Framework, and continues to execute on later versions of the .NET Framework, without any degradation of functionality.

Although the ADO.NET Components in the .NET Framework version 1.1 are designed to be both forward and backward compatible (excluding new features), there are several issues you need to be aware of that affect the forward or backward compatibility of an application.

The following information describes side-by-side execution issues that can affect the backward or forward compatibility of your ADO.NET code. The issues discussed in this topic are:

  • The .NET Framework Data Provider for ODBC
  • The .NET Framework Data Provider for Oracle
  • Code Access Security
  • The DataSet
  • SqlCommand Execution
  • MDAC Version

The .NET Framework Data Provider for ODBC

The .NET Framework Data Provider for ODBC (System.Data.Odbc) is included as a part of the .NET Framework, starting with version 1.1. However, the ODBC data provider is not included with the .NET Framework version 1.0. The ODBC data provider is available to .NET Framework version 1.0 developers as a Web download from https://msdn.microsoft.com/downloads. The namespace for the downloaded .NET Framework Data Provider for ODBC is Microsoft.Data.Odbc.

If you have an application developed for the .NET Framework version 1.0 that uses the ODBC data provider to connect to your data source, and you want to run that application on the .NET Framework version 1.1, you need to update the namespace for the ODBC data provider to System.Data.Odbc. Then, you need to recompile it for the .NET Framework version 1.1.

If you have an application developed for the .NET Framework version 1.1 that uses the ODBC data provider to connect to your data source, and you want to run that application on the .NET Framework version 1.0, you need to download the ODBC data provider and install it on the .NET Framework version 1.0 system. Then you need to update the namespace for the ODBC data provider to Microsoft.Data.Odbc, and recompile for the .NET Framework version 1.0.

The .NET Framework Data Provider for Oracle

The .NET Framework Data Provider for Oracle (System.Data.OracleClient) is included as a part of the .NET Framework starting with version 1.1. However, the data provider is not included with the .NET Framework version 1.0. The data provider is available to .NET Framework version 1.0 developers as a Web download from https://msdn.microsoft.com/downloads.

If you have an application developed for the .NET Framework version 1.1 that uses the data provider to connect to your data source, and you want to run that application on the .NET Framework version 1.0, you need to download the data provider and install it on the .NET Framework version 1.0 system.

Code Access Security

The .NET Framework data providers in the .NET Framework version 1.0 (System.Data.SqlClient, System.Data.OleDb) are required to run with FullTrust permission. Any attempt to use the .NET Framework data providers from the .NET Framework version 1.0 in a zone with less than FullTrust permission results in a SecurityException.

Now, in the .NET Framework version 1.1, the .NET Framework Data Provider for SQL Server can be used in partially trusted zones. The OLE DB and ODBC data providers still require FullTrust permission.

A new security feature, which enables you to restrict what connection strings can be used in a particular security zone, has been added for the .NET Framework data providers in the .NET Framework version 1.1. You can also disable the use of blank passwords for a particular security zone. For more information, see Code Access Security and ADO.NET.

Because each installation of the .NET Framework has a separate Security.config file (see Security Configuration Files), there are no forward or backward compatibility issues with security settings. However, if your application depends on the additional security capabilities of ADO.NET included in the .NET Framework version 1.1, you will not be able to distribute it to a version 1.0 system.

The DataSet

The DataSet in the .NET Framework version 1.1 contains several bug fixes that modify the behavior of the DataSet from the behavior in the .NET Framework version 1.0. You may encounter a backwards compatibility problem if your code is dependant on the behavior in version 1.0. The following changes have been made in the behavior of the DataSet.

  • Default column values that are set as empty strings in the XML Schema definition language (XSD) schema for a DataSet are no longer interpreted as null.

  • Constraints are validated after the Locale property is changed.

  • If the schema for your DataSet contains elements of the same name, but have different types, in the same namespace, version 1.1 throws an exception when you attempt to read the schema into a DataSet, or when the DataSet is remoted to a version 1.1 client. For example, if you have two related tables, and a column in the parent table has the same name as the child table, you encounter an exception if the Nested property of the DataRelation is true; as this places the child table in the same namespace as the parent table in the XML Schema for the DataSet. If the Nested property of the DataRelation is false, no exception is thrown.

  • Setting the AllowDBNull property of a column to false and the ColumnMapping property of the column to MappingType.Attribute represents a special case when remoting a DataSet. For a DataSet remoted from a version 1.0 system, an exception occurs when the client attempts to load the remoted DataSet. For a DataSet remoted from a version 1.1 system, no exception occurs. However, version 1.0 systems are unable to read the DefaultValue of the column. For version 1.0 systems, the column DefaultValue is String.Empty.

  • If the XML Schema for your DataSet includes a targetNamespace, data may not be read, and you may encounter exceptions when calling ReadXml to load the DataSet with XML that contains elements with no qualifying namespace. To read unqualified elements in this case, set elementFormDefault equal to "qualified" in your XML Schema. For example:

    <xsd:schema id="MyDataSet" 
      elementFormDefault="qualified"
      targetNamespace="http://www.tempuri.org/MyDataSet.xsd" 
      xmlns="http://www.tempuri.org/MyDataSet.xsd" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    </xsd:schema>
    

SqlCommand Execution

There is a behavior change, in how SqlCommand.ExecuteReader executes commands at the data source, in the .NET Framework version 1.1.

In the .NET Framework version 1.0, SqlCommand.ExecuteReader executes all commands in the context of the sp_executesql stored procedure. As a result, commands that affect the state of the connection (for example, SET NOCOUNT ON), only apply to the execution of the current command. The state of the connection is not modified for any subsequent commands executed while the connection is open.

In the .NET Framework version 1.1, SqlCommand.ExecuteReader only executes a command in the context of the sp_executesql stored procedure if the command contains parameters, as this provides a performance benefit. As a result, commands that affect the state of the connection, that are included in a non-parameterized command, modify the state of the connection for all subsequent commands executed while the connection is open.

Consider the following batch of commands executed in a call to SqlCommand.ExecuteReader.

SET NOCOUNT ON;
SELECT * FROM Customers;

In the .NET Framework version 1.1, NOCOUNT will remain ON for any subsequent commands executed while the connection is open. In the .NET Framework version 1.0, NOCOUNT is only ON for the current command execution.

This change can affect both the forward and backward compatibility of your application if you depend on the behavior of SqlCommand.ExecuteReader for either version of the .NET Framework.

For applications that run on both earlier and later versions of the .NET Framework, you can write your code to ensure that the behavior is the same regardless of the version you are running on. If you want to ensure that a command modifies the state of the connection for all subsequent commands, it is recommended that you execute your command using SqlCommand.ExecuteNonQuery. If you want to ensure that a command does not modify the connection for all subsequent commands, it is recommended that you include the commands to reset the state of the connection in your command. For example:

SET NOCOUNT ON;
SELECT * FROM Customers;
SET NOCOUNT OFF;

MDAC Version

The .NET Framework data providers for all versions of the .NET Framework require MDAC 2.6 or later to be installed. While this introduces no side-by-side execution issues, it is important to note that MDAC does not currently support side-by-side execution. Therefore, it is important to verify that your application will continue to function properly with the new version before upgrading the MDAC components for your installation.

See Also

Overview of ADO.NET | ADO.NET Architecture | Using .NET Framework Data Providers to Access Data