4.3. Configuring the DataMapper for .NET

The iBATIS DataMapper is configured using a central XML descriptor file, usually named SqlMap.config, which provides the details for your data source, data maps, and other features like caching, transactions, and thread management. At runtime, your application code will call a class method provided by the iBATIS library to read and parse your SqlMap.config file. After parsing the configuration file, a DataMapper client will be returned by iBATIS for your application to use.

4.3.1. DataMapper clients

Currently, the DataMapper framework revolves around the SqlMapper class, which acts as a facade to the DataMapper framework API. You can create a DataMapper client by instantiating an object of the SqlMapper class. An instance of the SqlMapper class (your DataMapper client) is created by reading a single configuration file. Each configuration file can specify one database or data source. However, you can use multiple DataMapper clients in your application. Just create another configuration file and pass the name of that file when the DataMapper client is created. The configuration files might use a different account with the same database, or reference different databases on different servers. You can read from one client and write to another, if that's what you need to do. See Section 4.4.1 for more details on building a SqlMapper instance, but first, let's take a look at the DataMapper configuration file.

4.3.2. DataMapper Configuration File (SqlMap.config)

A sample configuration file for a .NET web application is shown in Example 4.1. Not all configuration elements are required. The following sections describe the elements of this SqlMap.config file in more detail.

Example 4.1. Sample SqlMap.Config for a .NET Web Application (placed in same directory as web.config)

<?xml version="1.0" encoding="utf-8"?> 
<sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >

  <!-- Optional -->
  <properties resource="properties.config"/>

  <settings>
    <setting useStatementNamespaces="false"/>
    <setting cacheModelsEnabled="true"/>
    <setting validateSqlMap="false"/>
  </settings>

  <!-- Not required if providers.config is located in default location -->
  <providers embedded="resources.providers.config, IBatisNet.Test"/>

  <database>
    <provider name="sqlServer1.1"/>
    <dataSource name="NPetshop" 
                connectionString="user id=${username};
                password=${password};
                data source=${datasource};
                database=${database};"/>
  </database>

  <alias>
    <typeAlias alias="Account" type="IBatisNet.Test.Domain.Account, IBatisNet.Test"/>
    <typeAlias alias="YesNoBool"
         type="IBatisNet.Test.Domain.YesNoBoolTypeHandlerCallback, IBatisNet.Test"/>
  </alias>

  <typeHandlers>
    <typeHandler type="bool" dbType="Varchar" callback="YesNoBool"/>
  </typeHandlers>

  <sqlMaps>
    <sqlMap resource="${root}Maps/Account.xml"/>
    <sqlMap resource="${root}Maps/Category.xml"/>
    <sqlMap resource="${root}Maps/Product.xml"/>
  </sqlMaps> 
</sqlMapConfig>


4.3.3. DataMapper Configuration Elements

4.3.3.1. The <properties> Element

Sometimes the values we use in an XML configuration file occur in more than one element. Often, there are values that change when we move the application from one server to another. To help you manage configuration values, you can specify a standard properties file (with name=value entries) as part of a DataMapper configuration. Each named value in the properties file becomes a shell variable that can be used in the DataMapper configuration file and your Data Map definition files (see Section 3). For example, if the "properties" file contains

<?xml version="1.0" encoding="utf-8" ?> 
<settings>
  <add key="username" value="albert" />
</settings>

then all elements in the DataMapper configuration can use the variable ${username} to insert the value "albert". For example:

<dataSource connectionString="user id=${username};" 

Properties are handy during building, testing, and deployment by making it easy to reconfigure your application for multiple environments or use automated tools for configuration such as NAnt.

4.3.3.1.1. <properties> attributes

The <properties> element can accept one of the following attributes to specify the location of the properties file.

Table 4.3. Attributes of the <properties> element

AttributeDescription
resourceSpecify the properties file to be loaded from the root directory of the application
resource="properties.config"
urlSpecify the properties file to be loaded through an absolute path.
url="c:\Web\MyApp\Resources\properties.config"
-or-
url="file://c:\Web\MyApp\Resources\properties.config"
embeddedSpecify the properties file to be loaded as an embedded resource in an assembly. Syntax for the embedded attribute is '[extendednamespace.]filename, the name of the assembly which contains the embedded resource'
embedded="Resources.properties.config, MyApp.Data"

4.3.3.1.2. <property> element and attributes

You can also specify more than one properties file or add property keys and values directly into your SqlMap.config file by using <property> elements. For example:

<properties>
 <property resource="myProperties.config"/>
 <property resource="anotherProperties.config"/>
 <property key="host" value="ibatis.com" />
</properties>

Table 4.4. Attributes of the <property> element

AttributeDescription
resourceSpecify the properties file to be loaded from the root directory of the application
resource="properties.config"
urlSpecify the properties file to be loaded through an absolute path.
url="c:\Web\MyApp\Resources\properties.config"
-or-
url="file://c:\Web\MyApp\Resources\properties.config"
embeddedSpecify the properties file to be loaded as an embedded resource in an assembly. Syntax for the embedded attribute is '[extendednamespace.]filename, the name of the assembly which contains the embedded resource'
embedded="Resources.properties.config, MyApp.Data"
keyDefines a property key (variable) name
key="username"
valueDefines a value that will be used by the DataMapper in place of the the specified property key/variable
value="mydbuser"

4.3.3.2. The <providers> Element

Under ADO.NET, a database system is accessed through a provider. A database system can use a custom provider or a generic ODBC provider. The iBATIS .NET DataMapper uses a pluggable approach to using providers. Each provider is represented by an XML descriptor element found in a file called providers.config. The iBATIS .NET DataMapper distribution includes a standard providers.config file with a set of thirteen prewritten provider elements:

  • sqlServer1.0 - Microsoft SQL Server 7.0/2000 provider available with .NET Framework 1.0
  • sqlServer1.1 -Microsoft SQL Server 7.0/2000 provider available with .NET Framework 1.1
  • OleDb1.1 - OleDb provider available with .NET Framework 1.1
  • Odbc1.1 - Odbc provider available with .NET Framework 1.1
  • sqlServer2.0 -Microsoft SQL Server 7.0/2000/2005 provider available with .NET Framework 2.0
  • OleDb2.0 - OleDb provider available with .NET Framework 2.0
  • Odbc2.0 - Odbc provider available with .NET Framework 2.0
  • oracle9.2 - Oracle provider V9.2.0.401
  • oracle10.1 - Oracle provider V10.1.0.301
  • oracleClient1.0 - MS Oracle provider V1.0.5 available with .NET Framework 1.1
  • ByteFx - ByteFx MySQL provider V0.7.6.15073
  • MySql - MySQL provider V1.0.4.20163
  • SQLite3 - SQLite.NET provider V0.21.1869.3794
  • Firebird1.7 - Firebird SQL .NET provider V1.7.0.33200
  • PostgreSql0.7 - Npgsql provider V0.7.0.0
  • iDb2.10 - IBM DB2 iSeries provider V10.0.0.0

[Note]Note
If you use SQL Server 2005, you can configure the provider to allow Multiple Active Result Set (allowMARS="true") and add MultipleActiveResultSets=true in your connection string.

The providers.config file can be found under \source\IBatisNet.DataMapper.Test\bin\Debug in the iBATIS .NET source distribution or in the root folder of the .NET DataMapper binary distribution.

A provider may require libraries that you do not have installed,. Therefore, the provider element has an "enabled" attribute that allows you to disable unused providers. One provider can also be marked as the "default" and will be used if another is not specified by your configuration.

The standard providers.config file has sqlServer1.1 set as the default and the sqlServer1.0 provider disabled. Aside from sqlServer1.1, OleDb1.1, and Odbc1.1, all other providers are disabled by default. Remember to set the "enabled" attribute to "true" for the provider that you will be using.

[Important]Important

ByteFx is the recommended provider if you are using MySQL. You may download ByteFx from the MySQLNet SourceForge site (http://sf.net/projects/mysqlnet/). If the ByteFx license is acceptable to you, you may install it as a reference within your application and enable the ByteFx provider.

[Tip]Tip

Be sure to review the providers.config file and confirm that the provider you intend to use is enabled by setting the "enabled" attribute to "true".

Table 4.5. Expected default locations of the providers.config file

Windows, Library, or Test projects (using NUnit or equivalent)With the assembly (.dll) files with the app.config file
Web projectsIn the project base directory, with the web.config file

To use the file, you can copy it into your project at the expected default location, give a path to the file relative to the project root directory, specify a url (absolute path) to its location, or make it an embedded resource of your project. If you copy the file into the expected default location, the <providers> element is not required in your sqlMap.config file.

4.3.3.2.1. <providers> attributes

The <providers> element can accept one of the following attributes to specify the location of the providers.config file.

Table 4.6. Attributes of the <providers> element

AttributeDescription
resourceSpecify the file to be loaded from a relative path from the project root directory. Since the root directory is different depending on the project type, it is best to use a properties variable to indicate the relative path. Having that variable defined in a properties file makes it easy to change the path to all your Data Mapper configuration resources in one location.
resource="${root}providers.config"
urlSpecify the providers.config to be loaded through an absolute path.
url="c:\Web\MyApp\Resources\providers.config"
-or-
url="file://c:\Web\MyApp\Resources\providers.config"
embeddedSpecify the providers.config file to be loaded as an embedded resource in an assembly. Syntax for the embedded attribute is '[extendednamespace.]filename, the name of the assembly which contains the embedded resource'
embedded="Resources.providers.config, MyApp.Data"

4.3.3.3. The <settings> Element

There are three default settings used by the framework.. The settings appropriate for one application may not be appropriate for another. The <settings> element lets you configure these options and optimizations for the DataMapper instance that is created from the XML document. Each <settings> attribute has a default, and you can omit the <settings> element or any of its attributes. The <settings> attributes and the behavior they control are described in the following table.

Table 4.7. Attributes of the <settings> element

AttributeDescription
cacheModelsEnabled

This setting globally enables or disables all cache models for an DataMapper client. This can come in handy for debugging.

Example: cacheModelsEnabled=”true”
Default: true (enabled)

useStatementNamespaces

With this setting enabled, you must always refer to mapped statements by their fully qualified name, which is the combination of the sqlMap namesource and the statement id. For example: queryForObject(“Namespace.statement.Id”);

Example: useStatementNamespaces=”false”
Default: false (disabled)
validateSqlMap

This setting globally enables or disables the validation of mapping files against the SqlMapConfig.xsd schema. This can come in handy for debugging.

Example: validateSqlMap=”false”
Default: false (disabled)
useReflectionOptimizer

This setting globally enables or disables the usage of reflection to access property/filed value of C# object. The reflection optimizer use will emit types for retrieving, populating, instantiating parameter and result objects.

Example: useReflectionOptimizer=”true”
Default: true (enabled)

4.3.3.4. The <typeAlias> Element

The <typeAlias> element lets you specify a shorter name in lieu of a fully-qualified classname. For example:

  <typeAlias alias="LineItem" type="NPetshop.Domain.Billing.LineItem, NPetshop.Domain" />

You can then refer to LineItem where you would normally have to spell-out the fully qualified class name.

[Note]Note

In the .NET implementation, zero or more <typeAlias> elements can appear in the Data Map definition file, within an enclosing <alias> element.

4.3.3.4.1. <typeAlias> attributes

The <typeAlias> element has two attributes:

Table 4.8. Attributes of the <typeAlias> element

AttributeDescription
aliasA unique identifier for this element
alias="Category"
typeThe fully-qualified classname, including namespace reference
type=
"IBatisNet.Test.Domain.Category, 
IBatisNet.Test"


4.3.3.4.1.1. type Attribute
When specifying a type attribute for the configuration, the type attribute value must be a fully qualified type name in the following format:
type="[namespace.class], [assembly name],
     Version=[version], Culture=[culture],
     PublicKeyToken=[public token]"
For example:
type="MyProject.Domain.LineItem, MyProject.Domain,
     Version=1.2.3300.0, Culture=neutral,
     PublicKeyToken=b03f455f11d50a3a"
The strongly typed name is desired, although it is also legitimate to use the shorter style assembly type name:
type="MyProject.Domain.LineItem, MyProject.Domain"
4.3.3.4.2. Predefined type aliases

The framework predefines some aliases that you can use in your DataMapper configuration and data map files, as shown in Table 4.9.

Table 4.9. Predefined Aliases

CLR TypeAlias
System.ArrayListlist
System.BooleanBoolean, bool
System.ByteByte, byte
System.CharChar, char
System.DateTimedateTime, date
System.DecimalDecimal, decimal
System.DoubleDouble, double
System.Guidguid
System.Hashtablemap, hashmap, hashtable
System.Int16Int16, short, Short
System.Int32Int32, int, Int, integer, Integer
System.Int64Int64, long, Long
System.SByteSByte, sbyte
System.SingleFloat, float, Single, single
System.StringString, string
System.TimeSpanN/A
System.UInt16Short, short
System.UInt32Uint, uint
System.UInt64Ulong, ulong


4.3.3.5. The <typeHandler> Element

The <typeHandler> element allows for the configuration and use of a Custom Type Handler (see the Custom Type Handler section). This extends the DataMapper's capabilities in handling types that are specific to your database provider, are not handled by your database provider, or just happen to be a part of your application design.

  <typeHandler type="guid" dbType="Varchar2" callback="GuidVarchar"/>
[Note]Note

The DataMapper for .NET allows for zero or more <typeAlias> elements to appear in the Data Map definition file, within an enclosing <alias> element.

4.3.3.5.1. <typeHandler> attributes

The <typeHandler> element has three attributes:

Table 4.10. Attributes of the <typeAlias> element

AttributeDescription
typeRefers to the name of the type to handle
type="guid"
dbTypeIndicates the provider dbType to handle
dbType="Varchar2"
Note: Omit this attribute if you want the type handler to replace the default iBATIS type handler.
callbackThe alias of the custom type handler class name
callback="GuidVarchar"


4.3.3.6. The <database> Element

The <database> element encloses elements that configure the database system for use by the framework. These database configuration elements are the <provider> and <datasource> elements.

4.3.3.6.1. The <provider> Element

If the default provider is being used, the <provider> element is optional. Or, if several providers are available, one may be selected using the provider element without modifying the providers.config file.

<provider name="OleDb1.1"  />
4.3.3.6.2. The <datasource> element

The <datasource> element specifies the ADO.NET connection string. Example 4.2, shows sample elements for SQL Server, Oracle, Access, MySql, and PostgreSQL.

Example 4.2. Sample <datasource> and <provider> elements (.NET)

<!-- The ${properties} are defined in an external file, -->
<!-- but the values could also be coded inline. -->

<!-- Connecting to SQL Server -->
<database>
  <provider name="sqlServer1.1" />
  <dataSource name="NPetstore" default="true" 
       connectionString="data source=(local)\NetSDK;database=${database};
       user id=${username};password=${password};"/>
</database>

<!-- Connecting to Oracle -->
<database>
  <provider name="oracleClient1.0"/>
  <dataSource name="iBatisNet" 
       connectionString="Data Source=${datasource};User Id=${userid};Password=${password}"/>
</database>
 
<!-- Connecting to Access -->
<database>
  <provider name="OleDb1.1" />
  <dataSource name="NPetstore" default="true" 
       connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=${database}"/>
</database>

<!-- Connecting to a MySQL database --> 
<database>
  <provider name="ByteFx" />
  <dataSource name="NPetstore" default="true" 
       connectionString="Host=${host};Database=${database};
       Password=${password};Username=${username}" />
</database>

<!-- Connecting to a PostgreSQL database --> 
<database>
  <provider name="PostgreSql0.7" />
  <dataSource name="NPetstore" default="true" 
       connectionString="Server=${server};Port=5432;User Id=${userid};Password=${password};
       Database=${database};" />
</database>


4.3.3.7. The <sqlMap> Element

On a daily basis, most of your work will be with the Data Maps, which are covered by Section 3. The Data Maps define the actual SQL statements or stored procedures used by your application. The parameter and result objects are also defined as part of the Data Map. As your application grows, you may have several varieties of Data Map. To help you keep your Data Maps organized, you can create any number of Data Map definition files and incorporate them by reference in the DataMapper configuration. All of the definition files used by a DataMapper instance must be listed in the configuration file.

Example 4.3 shows <sqlMap> elements for loading a set of Data Map definitions. Note that the <sqlMap> elements are nested in a <sqlMaps> element. For more about Data Map definition files, see Section 3.

Example 4.3. Specifying sqlMap locations

<!-- Relative path from the project root directory using a property variable -->
<sqlMaps>
  <sqlMap resource="${root}Maps/Account.xml"/>
  <sqlMap resource="${root}Maps/Category.xml"/>
  <sqlMap resource="${root}Maps/Product.xml"/>
</sqlMaps>

<!-- Embedded resources using [extendednamespace.]filename, assemblyname -->
<sqlMaps>
  <sqlMap embedded="Maps.Account.xml, MyApp.Data"/>
  <sqlMap embedded="Maps.Category.xml, MyApp.Data"/>
  <sqlMap embedded="Maps.Product.xml, MyApp.Data"/>
</sqlMaps>

<!-- Full URL with a property variable -->
<sqlMaps>
  <sqlMap url="C:/${projectdir}/MyApp/Maps/Account.xml"/>
  <sqlMap url="C:/${projectdir}/MyApp/Maps/Category.xml"/>
  <sqlMap url="C:/${projectdir}/MyApp/Maps/Product.xml"/>
</sqlMaps>


[Tip]Tip

Since the application root directory location differs by project type (Windows, Web, or library), it is best to use a properties variable to indicate the relative path when using the <sqlMap> "resource" attribute. Having a variable defined in a properties file makes it easy to change the path to all your Data Mapper configuration resources in one location (note the ${projectdir} and ${root} variables in the example above).