using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Xml;
namespace BLToolkit.DataAccess
{
using Aspects;
using Common;
using Data;
using Data.DataProvider;
using Mapping;
using Patterns;
using Properties;
using Reflection;
using TypeBuilder;
[DataAccessor, DebuggerStepThrough]
public abstract class DataAccessor : DataAccessorBase
{
#region Constructors
protected DataAccessor()
{
}
protected DataAccessor(DbManager dbManager)
: base(dbManager)
{
}
protected DataAccessor(DbManager dbManager, bool dispose)
: base(dbManager, dispose)
{
}
#endregion
#region CreateInstance
public static DataAccessor CreateInstance(Type type)
{
return (DataAccessor)Activator.CreateInstance(TypeFactory.GetType(type));
}
public static DataAccessor CreateInstance(Type type, InitContext context)
{
return (DataAccessor)Activator.CreateInstance(TypeFactory.GetType(type), context);
}
public static DataAccessor CreateInstance(Type type, DbManager dbManager)
{
return CreateInstance(type, dbManager, false);
}
public static DataAccessor CreateInstance(
Type type,
InitContext context,
DbManager dbManager)
{
return CreateInstance(type, context, dbManager, false);
}
public static DataAccessor CreateInstance(Type type, DbManager dbManager, bool dispose)
{
DataAccessor da = CreateInstance(type);
da.SetDbManager(dbManager, dispose);
return da;
}
public static DataAccessor CreateInstance(
Type type,
InitContext context,
DbManager dbManager,
bool dispose)
{
DataAccessor da = CreateInstance(type, context);
da.SetDbManager(dbManager, dispose);
return da;
}
public static T CreateInstance<T>() where T : DataAccessor
{
return TypeFactory.CreateInstance<T>();
}
public static T CreateInstance<T>(DbManager dbManager)
where T : DataAccessor
{
return CreateInstance<T>(dbManager, false);
}
public static T CreateInstance<T>(DbManager dbManager, bool dispose)
where T : DataAccessor
{
T da = TypeFactory.CreateInstance<T>();
da.SetDbManager(dbManager, dispose);
return da;
}
#endregion
#region Protected Members
#region Parameters
[NoInterception]
protected virtual string GetQueryParameterName(DbManager db, string paramName)
{
return (string)db.DataProvider.Convert(paramName, ConvertType.NameToQueryParameter);
}
[NoInterception]
protected virtual string GetSpParameterName(DbManager db, string paramName)
{
return (string)db.DataProvider.Convert(paramName, db.GetConvertTypeToParameter());
}
[NoInterception]
protected virtual IDbDataParameter[] PrepareParameters(DbManager db, object[] parameters)
{
return db.PrepareParameters(parameters);
}
[NoInterception]
protected virtual IDbDataParameter GetParameter(DbManager db, string paramName)
{
IDbDataParameter p = db.Parameter(paramName);
if (p == null)
{
// This usually means that the parameter name is incorrect.
//
throw new DataAccessException(string.Format(
Resources.DataAccessot_ParameterNotFound, paramName));
}
// Input parameter mapping make no sence.
//
Debug.WriteLineIf(p.Direction == ParameterDirection.Input,
string.Format("'{0}.{1}' is an input parameter.",
db.Command.CommandText, paramName));
return p;
}
[NoInterception]
protected virtual IDbDataParameter[] CreateParameters(
DbManager db,
object obj,
string[] outputParameters,
string[] inputOutputParameters,
string[] ignoreParameters,
params IDbDataParameter[] commandParameters)
{
return db.CreateParameters(obj, outputParameters,
inputOutputParameters, ignoreParameters, commandParameters);
}
[NoInterception]
protected virtual IDbDataParameter[] CreateParameters(
DbManager db,
DataRow dataRow,
string[] outputParameters,
string[] inputOutputParameters,
string[] ignoreParameters,
params IDbDataParameter[] commandParameters)
{
return db.CreateParameters(dataRow, outputParameters,
inputOutputParameters, ignoreParameters, commandParameters);
}
[NoInterception]
protected virtual string PrepareSqlQuery(DbManager db, int queryID, int uniqueID, string sqlQuery)
{
return sqlQuery;
}
#endregion
#region ExecuteDictionary
protected void ExecuteDictionary(
DbManager db,
IDictionary dictionary,
Type objectType,
Type keyType,
string methodName)
{
bool isIndex = TypeHelper.IsSameOrParent(typeof(CompoundValue), keyType);
MemberMapper[] mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
if (mms.Length == 0)
throw new DataAccessException(string.Format(
Resources.DataAccessor_UnknownIndex,
GetType().Name, methodName));
if (mms.Length > 1 && keyType != typeof(object) && !isIndex)
throw new DataAccessException(string.Format(
Resources.DataAccessor_InvalidKeyType,
GetType().Name, methodName));
if (isIndex || mms.Length > 1)
{
string[] fields = new string[mms.Length];
for (int i = 0; i < mms.Length; i++)
fields[i] = mms[i].MemberName;
db.ExecuteDictionary(dictionary, new MapIndex(fields), objectType, null);
}
else
{
db.ExecuteDictionary(dictionary, mms[0].MemberName, objectType, null);
}
}
protected void ExecuteDictionary<TValue>(
DbManager db,
IDictionary<CompoundValue, TValue> dictionary,
Type objectType,
string methodName)
{
MemberMapper[] mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
if (mms.Length == 0)
throw new DataAccessException(string.Format(
Resources.DataAccessor_UnknownIndex,
GetType().Name, methodName));
string[] fields = new string[mms.Length];
for (int i = 0; i < mms.Length; i++)
fields[i] = mms[i].MemberName;
db.ExecuteDictionary<TValue>(dictionary, new MapIndex(fields), objectType, null);
}
protected void ExecuteDictionary<TKey, TValue>(
DbManager db,
IDictionary<TKey, TValue> dictionary,
Type objectType,
string methodName)
{
MemberMapper[] mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
if (mms.Length == 0)
throw new DataAccessException(string.Format(
Resources.DataAccessor_UnknownIndex,
GetType().Name, methodName));
if (mms.Length != 1)
throw new DataAccessException(string.Format(
Resources.DataAccessor_IndexIsComplex,
GetType().Name, methodName));
db.ExecuteDictionary<TKey, TValue>(dictionary, mms[0].MemberName, objectType, null);
}
protected void ExecuteScalarDictionary(
DbManager db,
IDictionary dictionary,
Type objectType,
Type keyType,
string methodName,
NameOrIndexParameter scalarField,
Type elementType)
{
bool isIndex = TypeHelper.IsSameOrParent(typeof(CompoundValue), keyType);
MemberMapper[] mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
if (mms.Length == 0)
throw new DataAccessException(string.Format(
Resources.DataAccessor_UnknownIndex,
GetType().Name, methodName));
if (mms.Length > 1 && keyType != typeof(object) && !isIndex)
throw new DataAccessException(string.Format(
Resources.DataAccessor_InvalidKeyType,
GetType().Name, methodName));
if (isIndex || mms.Length > 1)
{
string[] fields = new string[mms.Length];
for (int i = 0; i < mms.Length; i++)
fields[i] = mms[i].Name;
db.ExecuteScalarDictionary(dictionary, new MapIndex(fields), scalarField, elementType);
}
else
{
db.ExecuteScalarDictionary(
dictionary,
mms[0].Name,
keyType,
scalarField,
elementType);
}
}
#endregion
#region ExecuteEnumerable
protected IEnumerable<T> ExecuteEnumerable<T>(DbManager db, Type objectType, bool disposeDbManager)
{
try
{
using (IDataReader rd = db.ExecuteReader())
{
if (rd.Read())
{
ObjectMapper dest = MappingSchema.GetObjectMapper(objectType);
DataReaderMapper source = MappingSchema.CreateDataReaderMapper(rd);
InitContext ctx = new InitContext();
ctx.MappingSchema = MappingSchema;
ctx.ObjectMapper = dest;
ctx.DataSource = source;
ctx.SourceObject = rd;
int[] index = MappingSchema.GetIndex(source, dest);
IValueMapper[] mappers = ctx.MappingSchema.GetValueMappers(source, dest, index);
do
{
T destObject = (T)dest.CreateInstance(ctx);
if (ctx.StopMapping)
yield return destObject;
ISupportMapping smDest = destObject as ISupportMapping;
if (smDest != null)
{
smDest.BeginMapping(ctx);
if (ctx.StopMapping)
yield return destObject;
}
MappingSchema.MapInternal(source, rd, dest, destObject, index, mappers);
if (smDest != null)
smDest.EndMapping(ctx);
yield return destObject;
} while (rd.Read());
}
}
}
finally
{
if (disposeDbManager)
db.Dispose();
}
}
protected IEnumerable ExecuteEnumerable(DbManager db, Type objectType, bool disposeDbManager)
{
MappingSchema ms = db.MappingSchema;
if (disposeDbManager)
{
using (db)
using (IDataReader rd = db.ExecuteReader())
while (rd.Read())
yield return ms.MapDataReaderToObject(rd, objectType);
}
else
{
using (IDataReader rd = db.ExecuteReader())
while (rd.Read())
yield return ms.MapDataReaderToObject(rd, objectType);
}
}
#endregion
#region Convert
#region Primitive Types
[CLSCompliant(false)]
[NoInterception]
protected virtual SByte ConvertToSByte(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSByte(value);
}
[NoInterception]
protected virtual Int16 ConvertToInt16(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToInt16(value);
}
[NoInterception]
protected virtual Int32 ConvertToInt32(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToInt32(value);
}
[NoInterception]
protected virtual Int64 ConvertToInt64(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToInt64(value);
}
[NoInterception]
protected virtual Byte ConvertToByte(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToByte(value);
}
[CLSCompliant(false)]
[NoInterception]
protected virtual UInt16 ConvertToUInt16(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToUInt16(value);
}
[CLSCompliant(false)]
[NoInterception]
protected virtual UInt32 ConvertToUInt32(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToUInt32(value);
}
[CLSCompliant(false)]
[NoInterception]
protected virtual UInt64 ConvertToUInt64(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToUInt64(value);
}
[NoInterception]
protected virtual Char ConvertToChar(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToChar(value);
}
[NoInterception]
protected virtual Single ConvertToSingle(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSingle(value);
}
[NoInterception]
protected virtual Double ConvertToDouble(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToDouble(value);
}
[NoInterception]
protected virtual Boolean ConvertToBoolean(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToBoolean(value);
}
#endregion
#region Simple Types
[NoInterception]
protected virtual String ConvertToString(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToString(value);
}
[NoInterception]
protected virtual DateTime ConvertToDateTime(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToDateTime(value);
}
#if FW3
[NoInterception]
protected virtual DateTimeOffset ConvertToDateTimeOffset(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToDateTimeOffset(value);
}
[NoInterception]
protected virtual System.Data.Linq.Binary ConvertToLinqBinary(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToLinqBinary(value);
}
#endif
[NoInterception]
protected virtual Decimal ConvertToDecimal(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToDecimal(value);
}
[NoInterception]
protected virtual Guid ConvertToGuid(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToGuid(value);
}
[NoInterception]
protected virtual Stream ConvertToStream(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToStream(value);
}
[NoInterception]
protected virtual XmlReader ConvertToXmlReader(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToXmlReader(value);
}
[NoInterception]
protected virtual XmlDocument ConvertToXmlDocument(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToXmlDocument(value);
}
[NoInterception]
protected virtual Byte[] ConvertToByteArray(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToByteArray(value);
}
[NoInterception]
protected virtual Char[] ConvertToCharArray(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToCharArray(value);
}
#endregion
#region SqlTypes
[NoInterception]
protected virtual SqlByte ConvertToSqlByte(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlByte(value);
}
[NoInterception]
protected virtual SqlInt16 ConvertToSqlInt16(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlInt16(value);
}
[NoInterception]
protected virtual SqlInt32 ConvertToSqlInt32(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlInt32(value);
}
[NoInterception]
protected virtual SqlInt64 ConvertToSqlInt64(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlInt64(value);
}
[NoInterception]
protected virtual SqlSingle ConvertToSqlSingle(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlSingle(value);
}
[NoInterception]
protected virtual SqlBoolean ConvertToSqlBoolean(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlBoolean(value);
}
[NoInterception]
protected virtual SqlDouble ConvertToSqlDouble(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlDouble(value);
}
[NoInterception]
protected virtual SqlDateTime ConvertToSqlDateTime(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlDateTime(value);
}
[NoInterception]
protected virtual SqlDecimal ConvertToSqlDecimal(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlDecimal(value);
}
[NoInterception]
protected virtual SqlMoney ConvertToSqlMoney(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlMoney(value);
}
[NoInterception]
protected virtual SqlGuid ConvertToSqlGuid(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlGuid(value);
}
[NoInterception]
protected virtual SqlString ConvertToSqlString(DbManager db, object value, object parameter)
{
return db.MappingSchema.ConvertToSqlString(value);
}
#endregion
#region General case
[NoInterception]
protected virtual object ConvertChangeType(
DbManager db,
object value,
Type conversionType,
object parameter)
{
return db.MappingSchema.ConvertChangeType(value, conversionType);
}
#endregion
#endregion
#region IsNull
/// <summary>
/// Reserved for internal BLToolkit use.
/// </summary>
public interface INullableInternal
{
bool IsNull { [MustImplement(false, false)] get; }
}
[NoInterception]
protected virtual bool IsNull(
DbManager db,
object value,
object parameter)
{
// Speed up for scalar and nullable types.
//
switch (System.Convert.GetTypeCode(value))
{
// null, DBNull.Value, Nullable<T> without a value.
//
case TypeCode.Empty:
case TypeCode.DBNull:
return true;
case TypeCode.Object:
break;
// int, byte, string, DateTime and other primitives except Guid.
// Also Nullable<T> with a value.
//
default:
return false;
}
// Speed up for SqlTypes.
//
INullable nullable = value as INullable;
if (nullable != null)
return nullable.IsNull;
// All other types which have 'IsNull' property but does not implement 'INullable' interface.
// For example: 'Oracle.DataAccess.Types.OracleDecimal'.
//
// For types without 'IsNull' property the return value is always false.
//
INullableInternal nullableInternal =
(INullableInternal)DuckTyping.Implement(typeof(INullableInternal), value);
return nullableInternal.IsNull;
}
#endregion
protected SqlQueryAttribute GetSqlQueryAttribute(MethodInfo methodInfo)
{
object[] attrs = methodInfo.GetCustomAttributes(typeof(SqlQueryAttribute), true);
return (SqlQueryAttribute)attrs[0];
}
#endregion
}
} |