#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.Data; using System.Reflection; using System.Xml.Serialization; using IBatisNet.Common.Exceptions; using IBatisNet.Common.Utilities.TypesResolver; #endregion namespace IBatisNet.Common { /// /// Information about a data provider. /// [Serializable] [XmlRoot("provider", Namespace="http://ibatis.apache.org/providers")] public class Provider { #region Fields [NonSerialized] private string _assemblyName = string.Empty; [NonSerialized] private string _connectionClass = string.Empty; [NonSerialized] private string _commandClass = string.Empty; [NonSerialized] private string _dataParameter = string.Empty; [NonSerialized] private Type _dataParameterType = null; [NonSerialized] private string _parameterDbTypeClass = string.Empty; [NonSerialized] private Type _parameterDbType = null; [NonSerialized] private string _parameterDbTypeProperty = string.Empty; [NonSerialized] private string _dataAdapterClass = string.Empty; [NonSerialized] private string _commandBuilderClass = string.Empty; [NonSerialized] private string _name = string.Empty; [NonSerialized] private string _description = string.Empty; [NonSerialized] private bool _isDefault = false; [NonSerialized] private bool _isEnabled = true; [NonSerialized] private IDbConnection _templateConnection = null; [NonSerialized] private IDbCommand _templateCommand= null; [NonSerialized] private IDbDataAdapter _templateDataAdapter= null; [NonSerialized] private Type _commandBuilderType = null; [NonSerialized] private string _parameterPrefix = string.Empty; [NonSerialized] private bool _useParameterPrefixInSql = true; [NonSerialized] private bool _useParameterPrefixInParameter = true; [NonSerialized] private bool _usePositionalParameters = false; [NonSerialized] private bool _templateConnectionIsICloneable = false; [NonSerialized] private bool _templateCommandIsICloneable = false; [NonSerialized] private bool _templateDataAdapterIsICloneable = false; [NonSerialized] private bool _setDbParameterSize = true; [NonSerialized] private bool _setDbParameterPrecision = true; [NonSerialized] private bool _setDbParameterScale = true; [NonSerialized] private bool _useDeriveParameters = true; // private static readonly ILog _connectionLogger = LogManager.GetLogger("System.Data.IDbConnection"); #endregion #region Properties /// /// The name of the assembly which conatins the definition of the provider. /// /// Examples : "System.Data", "Microsoft.Data.Odbc" [XmlAttribute("assemblyName")] public string AssemblyName { get { return _assemblyName; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("AssemblyName"); _assemblyName = value; } } /// /// Tell us if it is the default data source. /// Default false. /// [XmlAttribute("default")] public bool IsDefault { get { return _isDefault; } set {_isDefault = value;} } /// /// Tell us if this provider is enabled. /// Default true. /// [XmlAttribute("enabled")] public bool IsEnabled { get { return _isEnabled; } set {_isEnabled = value;} } /// /// The connection class name to use. /// /// /// "System.Data.OleDb.OleDbConnection", /// "System.Data.SqlClient.SqlConnection", /// "Microsoft.Data.Odbc.OdbcConnection" /// [XmlAttribute("connectionClass")] public string ConnectionClass { get { return _connectionClass; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The connectionClass attribute is mandatory in the provider " + _name); _connectionClass = value; } } /// /// Does this ConnectionProvider require the use of a Named Prefix in the SQL /// statement. /// /// /// The OLE DB/ODBC .NET Provider does not support named parameters for /// passing parameters to an SQL Statement or a stored procedure called /// by an IDbCommand when CommandType is set to Text. /// /// For example, SqlClient requires select * from simple where simple_id = @simple_id /// If this is false, like with the OleDb or Obdc provider, then it is assumed that /// the ? can be a placeholder for the parameter in the SQL statement when CommandType /// is set to Text. /// [XmlAttribute("useParameterPrefixInSql")] public bool UseParameterPrefixInSql { get { return _useParameterPrefixInSql; } set { _useParameterPrefixInSql = value;} } /// /// Does this ConnectionProvider require the use of the Named Prefix when trying /// to reference the Parameter in the Command's Parameter collection. /// /// /// This is really only useful when the UseParameterPrefixInSql = true. /// When this is true the code will look like IDbParameter param = cmd.Parameters["@paramName"], /// if this is false the code will be IDbParameter param = cmd.Parameters["paramName"] - ie - Oracle. /// [XmlAttribute("useParameterPrefixInParameter")] public bool UseParameterPrefixInParameter { get { return _useParameterPrefixInParameter; } set { _useParameterPrefixInParameter = value; } } /// /// The OLE DB/OBDC .NET Provider uses positional parameters that are marked with a /// question mark (?) instead of named parameters. /// [XmlAttribute("usePositionalParameters")] public bool UsePositionalParameters { get { return _usePositionalParameters; } set { _usePositionalParameters = value; } } /// /// Used to indicate whether or not the provider /// supports parameter size. /// /// /// See JIRA-49 about SQLite.Net provider not supporting parameter size. /// [XmlAttribute("setDbParameterSize")] public bool SetDbParameterSize { get { return _setDbParameterSize; } set { _setDbParameterSize = value; } } /// /// Used to indicate whether or not the provider /// supports parameter precision. /// /// /// See JIRA-49 about SQLite.Net provider not supporting parameter precision. /// [XmlAttribute("setDbParameterPrecision")] public bool SetDbParameterPrecision { get { return _setDbParameterPrecision; } set { _setDbParameterPrecision = value; } } /// /// Used to indicate whether or not the provider /// supports a parameter scale. /// /// /// See JIRA-49 about SQLite.Net provider not supporting parameter scale. /// [XmlAttribute("setDbParameterScale")] public bool SetDbParameterScale { get { return _setDbParameterScale; } set { _setDbParameterScale = value; } } /// /// Used to indicate whether or not the provider /// supports DeriveParameters method for procedure. /// [XmlAttribute("useDeriveParameters")] public bool UseDeriveParameters { get { return _useDeriveParameters; } set { _useDeriveParameters = value; } } /// /// The command class name to use. /// /// /// "System.Data.SqlClient.SqlCommand" /// [XmlAttribute("commandClass")] public string CommandClass { get { return _commandClass; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The commandClass attribute is mandatory in the provider " + _name); _commandClass = value; } } /// /// The parameter class name to use. /// /// /// "System.Data.SqlClient.SqlParameter" /// [XmlAttribute("parameterClass")] public string ParameterClass { get { return _dataParameter; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The parameterClass attribute is mandatory in the provider " + _name); _dataParameter = value; } } /// /// The ParameterDbType class name to use. /// /// /// "System.Data.SqlDbType" /// [XmlAttribute("parameterDbTypeClass")] public string ParameterDbTypeClass { get { return _parameterDbTypeClass; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The parameterDbTypeClass attribute is mandatory in the provider " + _name); _parameterDbTypeClass = value; } } /// /// The ParameterDbTypeProperty class name to use. /// /// /// SqlDbType in SqlParamater.SqlDbType, /// OracleType in OracleParameter.OracleType. /// [XmlAttribute("parameterDbTypeProperty")] public string ParameterDbTypeProperty { get { return _parameterDbTypeProperty; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The parameterDbTypeProperty attribute is mandatory in the provider " + _name); _parameterDbTypeProperty = value; } } /// /// The dataAdapter class name to use. /// /// /// "System.Data.SqlDbType" /// [XmlAttribute("dataAdapterClass")] public string DataAdapterClass { get { return _dataAdapterClass; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The dataAdapterClass attribute is mandatory in the provider " + _name); _dataAdapterClass = value; } } /// /// The commandBuilder class name to use. /// /// /// "System.Data.OleDb.OleDbCommandBuilder", /// "System.Data.SqlClient.SqlCommandBuilder", /// "Microsoft.Data.Odbc.OdbcCommandBuilder" /// [XmlAttribute("commandBuilderClass")] public string CommandBuilderClass { get { return _commandBuilderClass; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The commandBuilderClass attribute is mandatory in the provider " + _name); _commandBuilderClass = value; } } /// /// Name used to identify the provider amongst the others. /// [XmlAttribute("name")] public string Name { get { return _name; } set { if ((value == null) || (value.Length < 1)) throw new ArgumentNullException("The name attribute is mandatory in the provider."); _name = value; } } /// /// Description. /// [XmlAttribute("description")] public string Description { get { return _description; } set { _description = value;} } /// /// Parameter prefix use in store procedure. /// /// @ for Sql Server. [XmlAttribute("parameterPrefix")] public string ParameterPrefix { get { return _parameterPrefix; } set { if ((value == null) || (value.Length < 1)) { _parameterPrefix = ""; //throw new ArgumentNullException("The parameterPrefix attribute is mandatory in the provider " + _name); } else { _parameterPrefix = value; } } } /// /// Check if this provider is Odbc ? /// [XmlIgnore] public bool IsObdc { get { return (_connectionClass.IndexOf(".Odbc.")>0); } } #endregion #region Constructor (s) / Destructor /// /// Do not use direclty, only for serialization. /// public Provider() { } #endregion #region Methods /// /// Init the provider. /// public void Initialize() { Assembly assembly; Type type; CachedTypeResolver cachedTypeResolver = new CachedTypeResolver(); try { assembly = Assembly.Load(_assemblyName); // Build the Command template type = assembly.GetType(_commandClass, true); _templateCommand = (IDbCommand)type.GetConstructor(Type.EmptyTypes).Invoke(null); // Build the DataAdapter template type = assembly.GetType(_dataAdapterClass, true); _templateDataAdapter = (IDbDataAdapter)type.GetConstructor(Type.EmptyTypes).Invoke(null); // Build the connection template type = assembly.GetType(_connectionClass, true); _templateConnection = (IDbConnection)type.GetConstructor(Type.EmptyTypes).Invoke(null); // Get the IDataParameter type _dataParameterType = assembly.GetType(_dataParameter, true); // Get the CommandBuilder Type _commandBuilderType = assembly.GetType(_commandBuilderClass, true); if (_parameterDbTypeClass.IndexOf(',')>0) { _parameterDbType = cachedTypeResolver.Resolve(_parameterDbTypeClass); } else { _parameterDbType = assembly.GetType(_parameterDbTypeClass, true); } _templateConnectionIsICloneable = _templateConnection is ICloneable; _templateCommandIsICloneable = _templateCommand is ICloneable; _templateDataAdapterIsICloneable = _templateDataAdapter is ICloneable; } catch(Exception e) { throw new ConfigurationException( string.Format("Could not configure providers. Unable to load provider named \"{0}\" not found, failed. Cause: {1}", _name, e.Message), e ); } } /// /// Get a connection object for this provider. /// /// An 'IDbConnection' object. public IDbConnection GetConnection() { // Cannot do that because on // IDbCommand.Connection = cmdConnection // .NET cast the cmdConnection to the real type (as SqlConnection) // and we pass a proxy --> exception invalid cast ! // if (_connectionLogger.IsDebugEnabled) // { // connection = (IDbConnection)IDbConnectionProxy.NewInstance(connection, this); // } if (_templateConnectionIsICloneable) { return (IDbConnection) ((ICloneable)_templateConnection).Clone(); } else { return (IDbConnection) Activator.CreateInstance(_templateConnection.GetType()); } } /// /// Get a command object for this provider. /// /// An 'IDbCommand' object. public IDbCommand GetCommand() { if (_templateCommandIsICloneable) { return (IDbCommand) ((ICloneable)_templateCommand).Clone(); } else { return (IDbCommand) Activator.CreateInstance(_templateCommand.GetType()); } } /// /// Get a dataAdapter object for this provider. /// /// An 'IDbDataAdapter' object. public IDbDataAdapter GetDataAdapter() { if (_templateDataAdapterIsICloneable) { return (IDbDataAdapter) ((ICloneable)_templateDataAdapter).Clone(); } else { return (IDbDataAdapter) Activator.CreateInstance(_templateDataAdapter.GetType()); } } /// /// Get a IDataParameter object for this provider. /// /// An 'IDataParameter' object. public IDataParameter GetDataParameter() { return (IDataParameter) Activator.CreateInstance(_dataParameterType); } /// /// Get the CommandBuilder Type for this provider. /// /// An object. public Type GetCommandBuilderType() { return _commandBuilderType; } /// /// Get the ParameterDb Type for this provider. /// /// An object. public Type ParameterDbType { get { return _parameterDbType; } } /// /// Equals implemantation. /// /// The test object. /// A boolean. public override bool Equals(object obj) { if ((obj != null) && (obj is Provider)) { Provider that = (Provider) obj; return ((this._name == that._name) && (this._assemblyName == that._assemblyName) && (this._connectionClass == that._connectionClass)); } return false; } /// /// A hashcode for the provider. /// /// An integer. public override int GetHashCode() { return (_name.GetHashCode() ^ _assemblyName.GetHashCode() ^ _connectionClass.GetHashCode()); } /// /// ToString implementation. /// /// A string that describes the provider. public override string ToString() { return "Provider " + _name; } #endregion } }