#region Apache Notice
/*****************************************************************************
* $Header: $
* $Revision$
* $Date$
*
* iBATIS.NET Data Mapper
* Copyright (C) 2004 - Gilles Bayon
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
********************************************************************************/
#endregion
#region Using
using System;
using System.Collections.Specialized;
using System.Data;
using System.Threading;
using System.Xml;
using IBatisNet.Common;
using IBatisNet.Common.Utilities;
using IBatisNet.DataAccess.Configuration;
using IBatisNet.DataAccess.Exceptions;
using IBatisNet.DataAccess.Interfaces;
using IBatisNet.DataAccess.SessionStore;
#endregion
namespace IBatisNet.DataAccess
{
///
/// DaoManager is a facade class that provides convenient access to the rest
/// of the DAO framework. It's primary responsibilities include:
/// - Reading configuration information and initializing the framework
/// - Managing different contexts for different configurations
/// - Providing access to Dao implementation
/// - Providing access to the DaoSession pool for connections, transactions
///
///
///
/// Exemple 1:
/// IDaoManager daoManager = DaoManager.GetInstance("PetStore");
/// ICategoryDao categoryDao = (ICategoryDao) daoManager.GetDao("Category");
/// DaoSession daoSession = daoManager.GetDaoSession();
/// daoSession.OpenConnection();
/// ArrayList categoryList = categoryGetCategoryList(5,daoSession);
/// daoSession.CloseConnection(daoSession);
///
/// Exemple 2:
/// IDaoManager daoManager = DaoManager.GetInstance("PetStore");
/// ICategoryDao categoryDao = (ICategoryDao) daoManager.GetDao("Category");
/// daoManager.OpenConnection();
/// ArrayList categoryList = categoryGetCategoryList(5);
/// daoManager.CloseConnection();
///
/// Exemple 3:
/// Product p1 = new Product();
/// Product p2 = new Product();
/// Category c 1= new Category()
/// c1.Add(p1);
/// c2.Add(p2);
///
/// IDaoManager daoManager = DaoManager.GetInstance("PetStore");
/// ICategoryDao categoryDao = (ICategoryDao) daoManager.GetDao("Category");
/// IProductDao productDao = (IProductDao) daoManager.GetDao("Product");
/// daoManager.BeginTransaction();
/// try
/// {
/// productInsert(p1);
/// productInsert(p2);
/// categoryInsert(c1);
/// daoManager.CommitTransaction();
/// }
///catch
///{
/// daoManager.RollBackTransaction();
///}
///
public class DaoManager : IDaoManager
{
#region Constants
///
/// Key for default context name
///
public const string DEFAULT_CONTEXT_NAME = "_DEFAULT_CONTEXT_NAME";
#endregion
#region Fields
///
///
///
///
///(contextName, daoManager)
///
protected static HybridDictionary DaoContextMap = new HybridDictionary();
private IDataSource _dataSource = null;
private IDbProvider _provider = null;
private string _name = string.Empty;
private IDaoSessionHandler _daoSessionHandler = null;
private bool _isDefault = false;
//(daoName, IDao)
private HybridDictionary _daoMap = new HybridDictionary();
//(dao implementation, Dao)
private static HybridDictionary _daoImplementationMap = new HybridDictionary();
///
/// Container session unique for each 'thread'.
///
private ISessionStore _sessionStore = null;
#endregion
#region Properties
///
/// Allow to set a custom session store like the
///
/// Set it after the configuration and before use of the
///
/// daoManager.SessionStore = new HybridWebThreadSessionStore( daoManager.Id );
///
public ISessionStore SessionStore
{
set { _sessionStore = value; }
}
///
/// Gets or sets the data source.
///
/// The data source.
internal IDataSource DataSource
{
get { return _dataSource; }
set { _dataSource = value; }
}
///
///
///
internal IDbProvider DbProvider
{
get { return _provider; }
set { _provider = value; }
}
///
/// Gets the local data source.
///
/// The local data source.
public IDataSource LocalDataSource
{
get { return _dataSource; }
}
///
/// DaoManager name
///
public string Id
{
get { return _name; }
set { _name = value; }
}
///
///
///
internal IDaoSessionHandler DaoSessionHandler
{
get { return _daoSessionHandler; }
set { _daoSessionHandler = value; }
}
///
///
///
internal bool IsDefault
{
get { return _isDefault; }
set { _isDefault = value; }
}
///
///
///
internal HybridDictionary DaoMap
{
get { return _daoMap; }
set { _daoMap = value; }
}
///
/// Gets the local DAO session.
///
/// The local DAO session.
public IDalSession LocalDaoSession
{
get
{
if (_sessionStore.LocalSession == null)
{
throw new DataAccessException("DaoManager could not invoke LocalDaoSession. No DaoSession was started. Call OpenConnection() or BeginTransaction first.");
}
return _sessionStore.LocalSession;
}
}
#endregion
#region Constructor (s) / Destructor
///
/// Make the default constructor private to prevent
/// instances from being created.
///
private DaoManager(string id)
{
Id = id;
_sessionStore = SessionStoreFactory.GetSessionStore(id);
}
#endregion
#region Methods
#region Configure
///
/// Configure an DaoManager from via the default file config.
/// (accesd as relative ressource path from your Application root)
///
[Obsolete("This method will be removed in a future version, use DomDaoManagerBuilder.Configure.", false)]
public static void Configure()
{
Configure( DomDaoManagerBuilder.DEFAULT_FILE_CONFIG_NAME );
}
///
/// Configure an DaoManager from via a file.
///
///
/// A relative ressource path from your Application root.
///
[Obsolete("This method will be removed in a future version, use DomDaoManagerBuilder.Configure.", false)]
public static void Configure(string resource)
{
XmlDocument document = Resources.GetResourceAsXmlDocument( resource );
new DomDaoManagerBuilder().BuildDaoManagers( document, false );
}
///
/// Configure and monitor the configuration file for modifications and
/// automatically reconfigure
///
///
/// Delegate called when a file is changed to rebuild the
///
[Obsolete("This method will be removed in a future version, use DomDaoManagerBuilder.Configure.", false)]
public static void ConfigureAndWatch(ConfigureHandler configureDelegate)
{
ConfigureAndWatch( DomDaoManagerBuilder.DEFAULT_FILE_CONFIG_NAME, configureDelegate );
}
///
/// Configure and monitor the configuration file for modifications and
/// automatically reconfigure
///
///
/// A relative ressource path from your Application root.
///
///
/// Delegate called when the file has changed, to rebuild the dal.
///
[Obsolete("This method will be removed in a future version, use DomDaoManagerBuilder.Configure.", false)]
public static void ConfigureAndWatch(string resource, ConfigureHandler configureDelegate)
{
ConfigWatcherHandler.ClearFilesMonitored();
ConfigWatcherHandler.AddFileToWatch( Resources.GetFileInfo( resource ) );
XmlDocument document = Resources.GetConfigAsXmlDocument( resource );
new DomDaoManagerBuilder().BuildDaoManagers( document, true );
TimerCallback callBackDelegate = new TimerCallback( DomDaoManagerBuilder.OnConfigFileChange );
StateConfig state = new StateConfig();
state.FileName = resource;
state.ConfigureHandler = configureDelegate;
new ConfigWatcherHandler( callBackDelegate, state );
}
#endregion
#region Static
///
/// Cleared all reference to
///
internal static void Reset()
{
//DaoManagerReverseLookup.Clear();
DaoContextMap.Clear();
}
///
/// Create anew instance of a DaoManager
///
/// A DaoManager.
internal static DaoManager NewInstance(string id)
{
return new DaoManager(id);
}
///
/// Gets the default DaoManager.
///
/// A DaoManager.
public static IDaoManager GetInstance()
{
return (DaoManager)DaoContextMap[DEFAULT_CONTEXT_NAME];
}
///
/// Gets a DaoManager registered with the specified id.
///
/// The name of the DaoManger.
/// A DaoManager.
public static IDaoManager GetInstance(string contextName)
{
return (DaoManager) DaoContextMap[contextName];
}
///
/// Get the DaoManager associated with this a Dao instance
///
/// A Dao instance.
/// A DaoManager
public static IDaoManager GetInstance(IDao dao)
{
Dao daoImplementation = _daoImplementationMap[dao] as Dao;
return daoImplementation.DaoManager;
}
///
/// Register a DaoManager
///
///
///
internal static void RegisterDaoManager(string contextName, DaoManager daoManager)
{
if ( DaoContextMap.Contains(contextName) )
{
throw new DataAccessException("There is already a DAO Context with the ID '" + contextName + "'.");
}
DaoContextMap.Add(contextName, daoManager);
if (daoManager.IsDefault==true)
{
if (DaoContextMap[DEFAULT_CONTEXT_NAME] == null)
{
DaoContextMap.Add(DEFAULT_CONTEXT_NAME, daoManager);
}
else
{
throw new DataAccessException("Error while configuring DaoManager. There can be only one default DAO context.");
}
}
}
#endregion
#region Work with DaoSession
///
/// Get a new DaoSession
///
///
public DaoSession GetDaoSession()
{
if (_daoSessionHandler == null)
{
throw new DataAccessException("DaoManager could not get DaoSession. DaoSessionHandler was null (possibly not configured).");
}
return _daoSessionHandler.GetDaoSession(this);
}
///
/// Determines whether [is DAO session started].
///
///
/// true if [is DAO session started]; otherwise, false.
///
public bool IsDaoSessionStarted()
{
return (_sessionStore.LocalSession != null);
}
///
/// Open a connection.
///
/// A IDalSession.
public IDalSession OpenConnection()
{
if (_daoSessionHandler== null)
{
throw new DataAccessException("DaoManager could not get DaoSession. DaoSessionPool was null (possibly not configured).");
}
if (_sessionStore.LocalSession != null)
{
throw new DataAccessException("DaoManager could not invoke OpenConnection(). A connection is already started. Call CloseConnection first.");
}
IDalSession session = _daoSessionHandler.GetDaoSession(this);
_sessionStore.Store(session);
session.OpenConnection();
return session;
}
///
/// Open a connection, on the specified connection string.
///
/// The connection string
public IDalSession OpenConnection(string connectionString)
{
if (_daoSessionHandler== null)
{
throw new DataAccessException("DaoManager could not get DaoSession. DaoSessionPool was null (possibly not configured).");
}
if (_sessionStore.LocalSession != null)
{
throw new DataAccessException("DaoManager could not invoke OpenConnection(). A connection is already started. Call CloseConnection first.");
}
IDalSession session = _daoSessionHandler.GetDaoSession(this);
_sessionStore.Store(session);
session.OpenConnection(connectionString);
return session;
}
///
/// Close a connection
///
public void CloseConnection()
{
if (_sessionStore.LocalSession == null)
{
throw new DataAccessException("DaoManager could not invoke CloseConnection(). No connection was started. Call OpenConnection() first.");
}
try
{
IDalSession session = _sessionStore.LocalSession;
session.CloseConnection();
}
catch(Exception ex)
{
throw new DataAccessException("DaoManager could not CloseConnection(). Cause :"+ex.Message, ex);
}
finally
{
_sessionStore.Dispose();
}
}
///
/// Begins a database transaction.
///
/// A IDalSession
public IDalSession BeginTransaction()
{
if (_daoSessionHandler == null)
{
throw new DataAccessException("DaoManager could not get DaoSession. DaoSessionPool was null (possibly not configured).");
}
if (_sessionStore.LocalSession != null)
{
throw new DataAccessException("DaoManager could not invoke BeginTransaction(). A DaoSession is already started. Call CommitTransaction() or RollbackTransaction first.");
}
IDalSession session = _daoSessionHandler.GetDaoSession(this);
_sessionStore.Store(session);
session.BeginTransaction();
return session;
}
///
/// Begins a database transaction with the specified isolation level.
///
///
/// The isolation level under which the transaction should run.
///
/// A IDalSession.
public IDalSession BeginTransaction(IsolationLevel isolationLevel)
{
if (_daoSessionHandler == null)
{
throw new DataAccessException("DaoManager could not get DaoSession. DaoSessionPool was null (possibly not configured).");
}
if (_sessionStore.LocalSession != null)
{
throw new DataAccessException("DaoManager could not invoke BeginTransaction(). A DaoSession is already started. Call CommitTransaction() or RollbackTransaction first.");
}
IDalSession session = _daoSessionHandler.GetDaoSession(this);
_sessionStore.Store(session);
session.BeginTransaction(isolationLevel);
return session;
}
///
/// Commits the database transaction.
///
///
/// Close the connection.
///
public void CommitTransaction()
{
if (_sessionStore.LocalSession == null)
{
throw new DataAccessException("DaoManager could not invoke CommitTransaction(). No Transaction was started. Call BeginTransaction() first.");
}
try
{
IDalSession session = _sessionStore.LocalSession;
session.CommitTransaction();
}
finally
{
_sessionStore.Dispose();
}
}
///
/// Rolls back a transaction from a pending state.
///
///
/// Close the connection.
///
public void RollBackTransaction()
{
if (_sessionStore.LocalSession == null)
{
throw new DataAccessException("DaoManager could not invoke RollBackTransaction(). No Transaction was started. Call BeginTransaction() first.");
}
try
{
IDalSession session = _sessionStore.LocalSession;
session.RollBackTransaction();
}
finally
{
_sessionStore.Dispose();
}
}
///
/// Release the local session.
///
/// Use in SqlMapDaoSession
internal void Dispose()
{
_sessionStore.Dispose();
}
#endregion
#region IDao access
///
/// Gets a Dao instance for the requested interface type.
///
public IDao this[Type daoInterface]
{
get
{
Dao dao = _daoMap[daoInterface] as Dao;
if (dao == null)
{
throw new DataException("There is no DAO implementation found for " + daoInterface.Name + " in this context.");
}
IDao idao = dao.Proxy;
return idao;
}
}
///
/// Gets a Dao instance for the requested interface type.
///
/// The requested interface type.
/// A Dao instance
public IDao GetDao(Type daoInterface)
{
return this[daoInterface];
}
///
/// Register a dao
///
///
internal void RegisterDao(Dao dao)
{
if ( DaoMap.Contains(dao.DaoInterface) )
{
throw new DataException("More than one implementation for '" + dao.Interface + "' was configured. " +
"Only one implementation per context is allowed.");
}
DaoMap.Add(dao.DaoInterface, dao);
_daoImplementationMap.Add(dao.Proxy, dao);
_daoImplementationMap.Add(dao.DaoInstance, dao);
}
#endregion
#endregion
}
}