The IBATIS.NET DataMapper API provides four core functions:
build a SqlMapper instance from a
          configuration file
execute an update query (including insert and delete).
execute a select query for a single object
execute a select query for a list of objects
The API also provides support for retrieving paginated lists and managing transactions.
| ![[Important]](images/important.png) | Important | 
|---|---|
| In prior versions of the DataMapper, the
         | 
An XML document is a wonderful tool for describing a database configuration (Section 4.3) or defining a set of data mappings (Section 3), but you can't execute XML. In order to use the iBATIS.NET configuration and definitions in your .NET application, you need a class you can call.
The framework provides service methods that you can call which
      read the configuration file (and any of its definition files) and builds
      a SqlMapper object. The
      SqlMapper object provides access to the rest of
      the framework. The SqlMapper is designed to be
      multi-threaded and long-lived, and so makes for a good singleton.
      Example 76 shows a singleton Mapper that is bundled with the
      framework.
Example 4.4. A Mapper singleton you can call from your own applications
[C#]
using IBatisNet.Common.Utilities;
using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Configuration;
namespace IBatisNet.DataMapper
{
 public class Mapper
 {
  private static volatile ISqlMapper _mapper = null;
  protected static void Configure (object obj)
  {
   _mapper = null;
  }
  protected static void InitMapper()
  {
   ConfigureHandler handler = new ConfigureHandler(Configure);
   DomSqlMapBuilder builder = new DomSqlMapBuilder();
   _mapper = builder.ConfigureAndWatch(handler);
  }
  public static ISqlMapper Instance()
  {
   if (_mapper == null)
   {
    lock (typeof (SqlMapper))
    {
     if (_mapper == null) // double-check
     { 
      InitMapper();
     }
    }
   }
   return _mapper;
  }
  
  public static ISqlMapper Get()
  {
   return Instance();
  }
 }
}To obtain the ISqlMapper instance, just
      call
[C#] ISqlMapper mapper = Mapper.Instance();
anywhere in your application, and specify one of the
      SqlMapper methods (see Section 5.3.2) . Here's an
      example:
[C#]
IList list = Mapper.Instance().QueryForList("PermitNoForYearList", values);The first time Mapper.Instance() is
      called, the DomSqlMapBuilder object will look for
      the SqlMap.config file in the default location for
      the type of project it is being used in and build a SqlMapper instance
      from that configuration. On subsequent calls, the cached
      mapper instance will be reused. The
      DomSqlMapBuilder.ConfigureAndWatch() method
      monitors changes to the configuration files. If the configuration or
      definitions files change, the SqlMapper will be
      safely reloaded. This is particularly useful in development, when you
      might make a change to a data map definition and want to see it take
      effect without restarting a debugging session. Likewise, in production,
      it can allow you to make changes to the definitions without reloading
      the rest of the application.
| ![[Tip]](images/tip.png) | Tip | 
|---|---|
| If you are using NUnit to test your mappings, you can run a test suite, make changes to the XML mapping document, and run the test again. NUnit will reload the configuration automatically. | 
| ![[Note]](images/note.png) | Note | 
|---|---|
| The ConfigureAndWatch method requires that your SqlMap.config file and data map files are accessible through the application's file system to be able to track file changes. | 
If for some reason you do not want to monitor changes to the
      configuration, you can create your own Mapper
      class, and use the Configure method
      instead:
[C#] ISqlMapper mapper = builder.Configure();
If you need access to more than one database from the same
        application, create a DataMapper configuration file for that database
        and another Mapper class to go with it. In the
        new Mapper class, change the call to
        ConfigureAndWatch to
[C#]
ISqlMapper mapper = builder.ConfigureAndWatch("anotherSqlMapConfig.config", handler);and substitute the name of your configuration file. Each database then has their own singleton you can call from your application:
[C#] ISqlMapper sqlServer = SqlServerMapper.Get(); ISqlMapper access = AccessMapper.Get();
iBATIS offers you a plethora of other options for loading your
        SqlMap.config file such as loading it through a
        Stream, Uri,
        FileInfo, or XmlDocument
        instance. All of these methods are available through the
        DomSqlMapBuilder API for creating a
        SqlMapper instance.
As seen in the prior section, the basic
        DomSqlMapBuilder.Configure() call will look
        for a file named SqlMap.config in your
        application's root directory. This directory's location differs by
        project type but is normally the directory where you place your
        web.config or app.config file.
If you have named your configuration file something other than
        SqlMap.config or if you have located your configuration file in a
        directory other than the application root directory, you can also pass
        in a relative or absolute file path to the
        Configure method.
Example 4.6. SqlMapper Configuration through an absolute or relative file path
/* Configure a SqlMapper from a file path.
   Uses a relative resource path from your application root 
   or an absolute file path such as "file:\\c:\dir\a.config" */
ISqlMapper mapper = builder.Configure(strPath);| ![[Tip]](images/tip.png) | Tip | 
|---|---|
| Since the application root directory location differs by project type (Windows, Web, or library), you can use an AppSettings key for defining a relative path to your SqlMap.config file. Having this key defined makes it easy to change the path without having to recompile your code: mapper = builder.Configure(
         ConfigurationSettings.AppSettings["rootPath"]+"SqlMap.config"); | 
Aside from using a simple string filepath, you can also pass in
        a FileInfo or Uri
        instance for the DomSqlMapBuilder to use in
        locating your SqlMap.config file.
Example 4.7. SqlMapper Configuration with a FileInfo or Uri instance
/* Configure a SqlMapper with FileInfo. */ FileInfo aFileInfo = someSupportClass.GetDynamicFileInfo(); ISqlMapper mapper = builder.Configure(aFileInfo); /* Configure a SqlMapper through a Uri. */ Uri aUri = someSupportClass.GetDynamicUri(); ISqlMapper anotherMapper = builder.Configure(aUri);
If you find that you already have loaded your DataMapper
        configuration information as an XmlDocument or
        Stream instance within your application, the
        DomSqlMapBuilder provides
        Configure overloads for those types as
        well.
Example 4.8. SqlMapper Configuration with an XmlDocument or Stream
/* Configure a SqlMapper with an XmlDocument */ XmlDocument anXmlDoc = someSupportClass.GetDynamicXmlDocument(); ISqlMapper mapper = builder.Configure(anXmlDoc); /* Configure a SqlMapper from a stream. */ Stream aStream = someSupportClass.GetDynamicStream(); ISqlMapper anotherMapper = builder.Configure(aStream);
The DomSqlMapBuilder API provides
        ConfigureAndWatch methods that can be used to
        monitor changes to the configuration files. This is particularly
        useful when using a singleton such as the
        Mapper class shown in the prior section. The
        example Mapper singleton allows a reconfigured
        SqlMapper instance to be reloaded on the
        fly.
Example 4.9. Mapper ConfigureHandler delegate
...
  protected static void Configure (object obj)
  {
   _mapper = null;
  }
  protected static void InitMapper()
  {
   ConfigureHandler handler = new ConfigureHandler(Configure);
   DomSqlMapBuilder builder = new DomSqlMapBuilder();
   _mapper = builder.ConfigureAndWatch(handler);
  }
...If you use a custom singleton, you will need to pass a
        ConfigureHandler (callback delegate) to the
        DomSqlMapBuilder so that it knows the method
        for resetting your application's SqlMapper
        instance. In the Mapper's case, its
        Configure method is used as the callback
        delegate.
Since the configuration files need to be watched for changes, your SqlMap.config file must be accessible through the file system. This means that configuration is limited to the three methods shown below.
Example 4.10. DomSqlMapBuilder ConfigureAndWatch methods
/* Configure and monitor the configuration file for modifications and automatically reconfigure the SqlMapper. This basic ConfigureAndWatch method looks for a file with the default name of SqlMap.config in the application root directory. */ public ISqlMapper ConfigureAndWatch(ConfigureHandler configureDelegate) /* Configure and monitor the configuration file for modifications and automatically reconfigure the SqlMapper. Uses a relative path from your application root or an absolute file path such as "file:\\c:\dir\a.config" */ public ISqlMapper ConfigureAndWatch( string resource, ConfigureHandler configureDelegate ) /* Configure and monitor the configuration file for modifications and automatically reconfigure the SqlMapper. Uses a FileInfo instance for your config file. */ public ISqlMapper ConfigureAndWatch( FileInfo resource, ConfigureHandler configureDelegate )
Before launching the 'Configure' method to build the ISqlMapper instance, you can set those porperties.
Table 4.11. Advanced settings
| Propertie | Description | 
|---|---|
| Properties | Allow to set properties before configuration. Those properties will be added to the properties list defined in the properties.config. NameValueCollection properties = new NameValueCollection();
properties.Add("connectionString", "...");
builder.Properties = properties;
ISqlMapper mapper = builder.Configure("sqlMap.config"); | 
| GetAccessorFactory | Allows to set a custom get accessor factory before configuration, see IGetAccessorFactory interface which defines the contract for the factory responsible to build set accessor for a member object in iBATIS. | 
| SetAccessorFactory | Allows to set a custom set accessor factory before configuration, see ISetAccessorFactory interface which defines the contract for the factory responsible to build get accessor for a member object in iBATIS. | 
| ObjectFactory | Allows to set a custom object factory before configuration, see IObjectFactory interface which defines the contract for the factory responsible for object creation in iBATIS. | 
| SqlMapper | Allows to set a custom SqlMapper before configuration, see ISqlMapper interface. | 
| ValidateSqlMapConfig | Enable whether or not the validation of configuration document before configuration | 
		
The ISqlMapper instance acts as a facade to
      provide access the rest of the DataMapper framework. The DataMapper API
      methods are shown in Example 4.11.
Example 4.11. The DataMapper API for .NET
[C#] /* Query API */ public object Insert(string statementName, object parameterObject); public int Update(string statementName, object parameterObject); public int Delete(string statementName, object parameterObject); public object QueryForObject(string statementName, object parameterObject); public T QueryForObject<T>(string statementName, object parameterObject); public object QueryForObject(string statementName, object parameterObject, object resultObject); public T QueryForObject<T>(string statementName, object parameterObject, T resultObject); public IList QueryForList(string statementName, object parameterObject); public IList<T> QueryForList<T>(string statementName, object parameterObject); public void QueryForList(string statementName, object parameterObject, IList resultObject); public void QueryForList<T>(string statementName, object parameterObject, IList<T> resultObject); public IList QueryForList(string statementName, object parameterObject, int skipResults, int maxResults); public IList<T> QueryForList<T>(string statementName, object parameterObject, int skipResults, int maxResults); public IList QueryWithRowDelegate(string statementName, object parameterObject, RowDelegate rowDelegate); public IList<T> QueryWithRowDelegate<T>(string statementName, object parameterObject, SqlMapper.RowDelegate<T> rowDelegate); [Obsolete] public PaginatedList QueryForPaginatedList(String statementName, object parameterObject, int pageSize); public IDictionary QueryForDictionary(string statementName, object parameterObject, string keyProperty) IDictionary<K, V> QueryForDictionary<K, V>(string statementName, object parameterObject, string keyProperty); public IDictionary QueryForDictionary(string statementName, object parameterObject, string keyProperty, string valueProperty) public IDictionary<K, V> QueryForDictionary<K, V>(string statementName, object parameterObject, string keyProperty, string valueProperty); public IDictionary QueryForMap(string statementName, object parameterObject, string keyProperty) public IDictionary QueryForMap(string statementName, object parameterObject, string keyProperty, string valueProperty) /* Connection API */ public void OpenConnection() public void CloseConnection() /* Transaction API */ public void BeginTransaction() public void BeginTransaction(bool openConnection) public void BeginTransaction(IsolationLevel isolationLevel) public void BeginTransaction(bool openConnection, IsolationLevel isolationLevel) public void CommitTransaction() public void CommitTransaction(bool closeConnection) public void RollBackTransaction() public void RollBackTransaction(bool closeConnection)
Note that each of the API methods accept the name of the Mapped
        Statement as the first parameter. The statementName
        parameter corresponds to the id of the Mapped
        Statement in the Data Map definition (see Section 3.3). In each case,
        a parameterObject also may be passed. If the
        Mapped Statement expects no parameters, a null
        parameterObject may be passed. If a statement
        does expect parameters, then a valid
        parameterObject is required. The following
        sections describe how the API methods work.
public object Insert(string statementName,
                     object parameterObject);
public int Update(string statementName,
                  object parameterObject);
public int Delete(string statementName,
                  object parameterObject);If a Mapped Statement uses one of the <insert>,
        <update>, or <delete> statement-types, then it should use
        the corresponding API method. The <insert> element supports a
        nested <selectKey> element for generating primary keys (see
        Section 3.3.3). If the <selectKey> stanza is used, then
        Insert returns the generated key; otherwise a
        null object is returned. Both the Update and
        Delete methods return the number of rows
        affected by the statement.
public object QueryForObject(string statementName,
                             object parameterObject);
public object QueryForObject(string statementName, 
                             object parameterObject,
                             object resultObject);
public T QueryForObject<T>(string statementName, object parameterObject);
public T QueryForObject<T>(string statementName, object parameterObject, T resultObject);
If a Mapped Statement is expected to select a single row, then
        call it using QueryForObject. Since the
        Mapped Statement definition specifies the result class expected, the
        framework can both create and populate the result class for you.
        Alternatively, if you need to manage the result object yourself, say
        because it is being populated by more than one statement, you can use
        the alternate form and pass your resultObject
        as the third parameter.
public IList QueryForList(string statementName,
                          object parameterObject);
public void QueryForList(string statementName,
                         object parameterObject,
                         IList resultObject);
public IList QueryForList(string statementName,
                          object parameterObject,
                          int skipResults,
                          int maxResults);
public IList<T> QueryForList<T>(string statementName, object parameterObject);
public void QueryForList<T>(string statementName, 
                                  object parameterObject, 
								  IList<T> resultObject);
public IList<T> QueryForList<T>(string statementName, 
                                            object parameterObject,
                                            int skipResults, int maxResults);						  
						  If a Mapped Statement is expected to select multiple rows, then
        call it using QueryForList . Each entry in
        the list will be an result object populated from the corresponding row
        of the query result. If you need to manage the resultObject yourself,
        then it can be passed as the third parameter.
If you need to obtain a partial result, the third form takes the
        number of records to skip (the starting point) and the maximum number
        to return, as the skipResults and
        maxResults parameters. The
        PaginatedList method provides the same
        functionality but in a more convenient wrapper. 
		
The
        QueryWithRowDelegate method also works with
        multiple rows, but provides a post-processing feature.
public delegate void RowDelegate(object obj,
                                 IList list);
public IList QueryWithRowDelegate(string statementName,
                                  object parameterObject, 
                                  RowDelegate rowDelegate);
public IList<T> QueryWithRowDelegate<T>(string statementName, object parameterObject, 
                                SqlMapper.RowDelegate<T> rowDelegate);								  
								  No matter how well our database is designed or how cleverly we
        describe our maps, the result objects we get back may not be ideal.
        You may need to perform some post-processing task on the result
        objects. You might even want to omit an entry omitted from the list.
        Or, you might want to use the result object to create some other, more
        useful object. To save filtering the result objects from to one list
        to another, you can pass a RowDelegate to the
        method to do the dirty work. The SqlMapper will
        go through each of the result objects and give the delegate a chance
        to modify the object and determine if the object should be added to
        the IList that will be returned.
        
| ![[Important]](images/important.png) | Important | 
|---|---|
| It is your responsibility to add the objects you want returned to the list. If an object is not added, it is not returned. | 
public delegate void DictionaryRowDelegate(object key, 
                                           object value, 
                                           object parameterObject, 
                                           IDictionary dictionary);
public IDictionary QueryForMapWithRowDelegate(string statementName,
                                              object parameterObject, 
                                              string keyProperty, 
                                              string valueProperty, 
                                              DictionaryRowDelegate rowDelegate);No matter how well our database is designed or how cleverly we
        describe our maps, the result objects we get back may not be ideal.
        You may need to perform some post-processing task on the result
        objects. You might even want to omit an entry omitted from the
        dictionary. Or, you might want to use the result object to create some
        other, more useful object. To save filtering the result objects from
        to one dictionary to another, you can pass a
        DictionaryRowDelegate to the method to do the
        dirty work. The SqlMapper will go through each
        of the result objects and give the delegate a chance to modify the
        object and determine if the object should be added to the
        IDictionary  that will be returned.
        
| ![[Important]](images/important.png) | Important | 
|---|---|
| It is your responsibility to add the objects you want returned to the dictionary. If an object is not added, it is not returned. | 
| ![[Note]](images/note.png) | Note | 
|---|---|
| The method PaginatedList has been made as obsolete and will not be supported in future version. | 
public PaginatedList QueryForPaginatedList(string statementName,
                                           object parameterObject,
                                           int pageSize);We live in an age of information overflow. A database query often returns more hits than users want to see at once, and our requirements may say that we need to offer a long list of results a "page" at a time. If the query returns 1000 hits, we might need to present the hits to the user in sets of fifty, and let them move back and forth between the sets. Since this is such a common requirement, the framework provides a convenience method.
The PaginatedList interface includes
        methods for navigating through pages
        (nextPage(),
        previousPage(), gotoPage()) and
        also checking the status of the page
        (isFirstPage(),
        isMiddlePage(),
        isLastPage(),
        isNextPageAvailable(),
        isPreviousPageAvailable(),
        getPageIndex(),
        getPageSize()). Although the total number of
        records available is not accessible from the
        PaginatedList interface, this should be easily
        accomplished by simply executing a second statement that counts the
        expected results. Too much overhead would be associated with the
        PaginatedList otherwise.
| ![[Tip]](images/tip.png) | Tip | 
|---|---|
| The  | 
public IDictionary QueryForDictionary(string statementName,
                                      object parameterObject,
                                      string keyProperty)
public IDictionary<K, V> QueryForDictionary<K, V>(string statementName, 
                                      object parameterObject, 
                                      string keyProperty);
public IDictionary QueryForDictionary(string statementName,
                                      object parameterObject,
                                      string keyProperty,
                                      string valueProperty)
public IDictionary<K, V> QueryForDictionary<K, V>(string statementName, 
                                     object parameterObject, 
                                      string keyProperty, 
									  string valueProperty);
public IDictionary QueryForMap(string statementName,
                               object parameterObject, 
                               string keyProperty)
public IDictionary QueryForMap(string statementName, 
                               object parameterObject, 
                               string keyProperty, 
                               string valueProperty)The QueryForList methods return the
        result objects within a IList instance.
        Alternatively, the QueryForDictionary returns
        a IDictionary instance. The value of
        each entry is one of the result objects. The key to each entry is
        indicated by the keyProperty parameter. This is
        the name of the one of the properties of the result object, the value
        of which is used as the key for each entry. For example, If you needed
        a set of Employee objects, you might want them
        returned as a IDictionary keyed by each
        object's EmployeeNumber property.
If you don't need the entire result object in your
        Dictionary, you can add the
        valueProperty parameter to indicate which
        result object property should be the value of an entry. For example,
        you might just want the EmployeeName keyed by
        EmployeeNumber. 
| ![[Important]](images/important.png) | Important | 
|---|---|
| You do not need to use this method just to obtain an
             | 
The QueryforMap methods provide the
        same functionality but under a different name, for the sake of
        consistency with the Java implementation. (The .NET
        IDictionary interface is equivalent to
        the Java Map interface.)
In the iBATIS DataMapper framework, a session is a container for an ADO connection and transaction.
The DataMapper's IDalSession implements the
      IDisposable interface. So you can use it with the
      using syntax.
Example 4.13. using instruction
[C#]
using ( IDalSession session = sqlMap.OpenConnection() )
{
  Account account = sqlMap.QueryForObject("GetAccountViaColumnName", 1) as Account;
}| ![[Note]](images/note.png) | Note | 
|---|---|
| Sessions cannot be nested. An exception will be thrown if you
        call
         | 
The DataMapper API includes methods to demarcate connection boundaries.
// Open a session : Open an ADO connection public void OpenConnection() // Close a session : Close the associated ADO connection public void CloseConnection()
Example 4.14. Connection example
[C#] sqlMap.OpenConnection() Account account = sqlMap.QueryForObject("GetAccountViaColumnName", 1) as Account; sqlMap.CloseConnection() // Same thing with using instruction using ( IDalSession session = sqlMap.OpenConnection() ) { Account account = sqlMap.QueryForObject("GetAccountViaColumnName", 1) as Account; }
By default, calling any of the API methods (see Section 4.4.2) on
      a SqlMapper instance will auto-open/close a
      connection. This means that each call to these methods will be a single
      unit of work. For many cases, this simple approach may be sufficient.
      But it is not ideal if you have a number of statements that must execute
      as a single unit of work, which is to say, succeed or fail as a group.
      For cases like these, you can use explicit
      transactions.
An example of using automatic session is shown as Example 4.14.
Example 4.15. Using automatic session
[C#]
Item item = (Item) sqlMap.executeQueryForObject ("GetItem", itemId);
item.Description = "test";
// No session demarcated, so open/close connection will be automatic (implied)
sqlMap.Update("UpdateItem", item);
item.Description = newDescription;
item.Description = "test2";
// No transaction demarcated, so open/close connection will be automatic (implied)
sqlMap.Update("UpdateItem", item);| ![[Note]](images/note.png) | Note | 
|---|---|
| Be careful to consider sessions when framing your queries.
        Automatic sessions are convenient, but you will run into trouble if
        your unit of work requires more than a single update to the database.
        In Example 4.14, if the second call to
         | 
The DataMapper API includes methods to demarcate transactional
      boundaries. A transaction can be started, committed and/or rolled back.
      You can call the transaction methods from the
      SqlMapper instance.
// Begin a transactional session : Open a connection and begin an ADO transaction public void BeginTransaction() // Begin a transactional session : Open a connection is specified and begin an ADO transaction public void BeginTransaction(bool openConnection) // Begin a transactional session : Open a connection and begin an ADO transaction // with the specified IsolationLevel public void BeginTransaction(IsolationLevel isolationLevel) // Begin a transactional session : Open a connection is specified and begin an ADO transaction // with the specified IsolationLevel public void BeginTransaction(bool openConnection, IsolationLevel isolationLevel) // Commit a session : Commit the ADO transaction and close the connection public void CommitTransaction() // Commit a session : Commit the ADO transaction and close the connection if specified public void CommitTransaction(bool closeConnection) // RollBack a session : RollBack the ADO transaction and close the connection public void RollBackTransaction() // RollBack a session : RollBack the ADO transaction and close the connection if specified public void RollBackTransaction(bool closeConnection)
An example of using transactions is shown as Example 4.15.
Example 4.16. Using transactions
[C#]
try 
  {
      sqlMap.BeginTransaction();
      Item item = (Item) sqlMap.QueryForObject("getItem", itemId);
      item.Description = newDescription;
      sqlMap.Update("updateItem", item);
      sqlMap.CommitTransaction();
  } 
catch {
      sqlMap.RollBackTransaction();
}
 
// With "using" syntax
using ( IDalSession session = sqlMap.BeginTransaction() )
{
  Item item = (Item) sqlMap.QueryForObject("getItem", itemId);
  item.Description = newDescription;
  sqlMap.Update("updateItem", item);
  session.Complete(); // Commit
}
Distributed transactions are transactions that can span multiple resource managers, such as SQL Server and Oracle, and reconcile transactions among them.
iBATIS.NET introduces a new
      TransactionScope class mimicking the new
      TransactionScope found in the
      System.Transactions namespace (.NET Framework
      2.0). This class supports MSMQ, ADO.NET, SqlServer, and DTC transaction
      models. This is a simple managed interface to COM+'s SWC (Services
      Without Components) Transactions. It can be used only by developers
      using .NET 1.1 and Windows XP SP2 or Windows Server 2003 since it
      implements distributed transactional support using the
      ServiceDomain class.
Usage is simple, as seen in the following example where a code block is made transactional à la Indigo (moving to Indigo will be easier since it is the same API):
Example 4.17. Using distributed transactions
[C#] using IBatisNet.Common.Transaction; using (TransactionScope tx = new TransactionScope()) { sqlMapSqlServer.OpenConnection(); // Transaction will be automatically associated account = sqlMapSqlServer.QueryForObject("GetAccount", accountId) as Account; account.FirstName = "Gilles"; sqlMapSqlServer.Update(account); sqlMapSqlServer.CloseConnection(); sqlMapOracle.OpenConnection(); // Transaction will be automatically associated product = sqlMapOracle.QueryForObject("GetProduct", productId) as Product; product.Quantity = 1000; sqlMapOracle.Update(product); sqlMapOracle.CloseConnection(); tx.Complete(); // Commit }
It is important to make sure that each instance of this class
        gets Close()'d. The easiest way to ensure
        that each instance is closed is with the using
        statement in C#. When Dispose is called on
        the transaction scope at the end of the using code
        block, the ambient transaction will be commited
        only if the Complete() method has been
        called.
| ![[Note]](images/note.png) | Note | 
|---|---|
| This  | 
Example 4.18. Executing Update (insert, update, delete)
[C#] Product product = new Product(); product.Id = 1; product.Description = “Shih Tzu”; int key = sqlMap.Insert (“insertProduct”, product);
 
Example 4.19. Executing Query for Object (select)
[C#] int key = 1; Product product = sqlMap.QueryForObject (“getProduct”, key) as Product;
 
Example 4.20. Executing Query for Object (select) With Preallocated Result Object
[C#] Customer customer = new Customer(); sqlMap.BeginTransaction(); sqlMap.QueryForObject(“getCust”, parameterObject, customer); sqlMap.QueryForObject(“getAddr”, parameterObject, customer); sqlMap.CommitTransaction();
 
Example 4.21. Executing Query for List (select)
[C#] IList list = sqlMap.QueryForList (“getProductList”, null);
 
Example 4.22. Auto-Open/Close
[C#]
// When OpenConnection is not called, the statements will auto-Open/Close. 
int key = sqlMap.Insert (“insertProduct”, product);
 
Example 4.23. Executing Query for List (select) With Result Boundaries
[C#] List list = sqlMap.queryForList (“getProductList”, null, 0, 40);
 
Example 4.24. Executing Query with a RowHandler (select)
[C#]
public void RowHandler(object obj, IList list)
{
  Product product = (Product) object;
  product.Quantity = 10000;
}
SqlMapper.RowDelegate handler = new SqlMapper.RowDelegate(this.RowHandler);
IList list = sqlMap.QueryWithRowDelegate("getProductList", null, handler);
 
Example 4.25. Executing Query for Paginated List (select)
[C#] PaginatedList list = sqlMap.QueryForPaginatedList (“getProductList”, null, 10); list.NextPage(); list.PreviousPage();
 
Example 4.26. Executing Query for Map
[C#] IDictionary map = sqlMap.QueryForMap (“getProductList”, null, “productCode”); Product p = (Product) map[“EST-93”];