using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using NPoco.DatabaseTypes;
using NPoco.Expressions;
using NPoco.Linq;
namespace NPoco
{
///
/// Base class for DatabaseType handlers - provides default/common handling for different database engines
///
public abstract class DatabaseType
{
// Helper Properties
public static DatabaseType SqlServer2012 { get { return Singleton.Instance; } }
public static DatabaseType SqlServer2008 { get { return Singleton.Instance; } }
public static DatabaseType SqlServer2005 { get { return Singleton.Instance; } }
public static DatabaseType PostgreSQL { get { return Singleton.Instance; } }
public static DatabaseType Oracle { get { return Singleton.Instance; } }
public static DatabaseType OracleManaged { get { return Singleton.Instance; } }
public static DatabaseType MySQL { get { return Singleton.Instance; } }
public static DatabaseType SQLite { get { return Singleton.Instance; } }
public static DatabaseType SQLCe { get { return Singleton.Instance; } }
public static DatabaseType Firebird { get { return Singleton.Instance; } }
readonly Dictionary typeMap;
public DatabaseType()
{
typeMap = new Dictionary();
typeMap[typeof(byte)] = DbType.Byte;
typeMap[typeof(sbyte)] = DbType.SByte;
typeMap[typeof(short)] = DbType.Int16;
typeMap[typeof(ushort)] = DbType.UInt16;
typeMap[typeof(int)] = DbType.Int32;
typeMap[typeof(uint)] = DbType.UInt32;
typeMap[typeof(long)] = DbType.Int64;
typeMap[typeof(ulong)] = DbType.UInt64;
typeMap[typeof(float)] = DbType.Single;
typeMap[typeof(double)] = DbType.Double;
typeMap[typeof(decimal)] = DbType.Decimal;
typeMap[typeof(bool)] = DbType.Boolean;
typeMap[typeof(string)] = DbType.String;
typeMap[typeof(char)] = DbType.StringFixedLength;
typeMap[typeof(Guid)] = DbType.Guid;
typeMap[typeof(DateTime)] = DbType.DateTime;
typeMap[typeof(DateTimeOffset)] = DbType.DateTimeOffset;
typeMap[typeof(TimeSpan)] = DbType.Time;
typeMap[typeof(byte[])] = DbType.Binary;
typeMap[typeof(byte?)] = DbType.Byte;
typeMap[typeof(sbyte?)] = DbType.SByte;
typeMap[typeof(short?)] = DbType.Int16;
typeMap[typeof(ushort?)] = DbType.UInt16;
typeMap[typeof(int?)] = DbType.Int32;
typeMap[typeof(uint?)] = DbType.UInt32;
typeMap[typeof(long?)] = DbType.Int64;
typeMap[typeof(ulong?)] = DbType.UInt64;
typeMap[typeof(float?)] = DbType.Single;
typeMap[typeof(double?)] = DbType.Double;
typeMap[typeof(decimal?)] = DbType.Decimal;
typeMap[typeof(bool?)] = DbType.Boolean;
typeMap[typeof(char?)] = DbType.StringFixedLength;
typeMap[typeof(Guid?)] = DbType.Guid;
typeMap[typeof(DateTime?)] = DbType.DateTime;
typeMap[typeof(DateTimeOffset?)] = DbType.DateTimeOffset;
typeMap[typeof(TimeSpan?)] = DbType.Time;
typeMap[typeof(Object)] = DbType.Object;
}
///
/// Configire the specified type to be mapped to a given db-type
///
protected void AddTypeMap(Type type, DbType dbType)
{
typeMap[type] = dbType;
}
internal const string LinqBinary = "System.Data.Linq.Binary";
public virtual DbType? LookupDbType(Type type, string name)
{
DbType dbType;
var nullUnderlyingType = Nullable.GetUnderlyingType(type);
if (nullUnderlyingType != null) type = nullUnderlyingType;
if (type.IsEnum && !typeMap.ContainsKey(type))
{
type = Enum.GetUnderlyingType(type);
}
if (typeMap.TryGetValue(type, out dbType))
{
return dbType;
}
if (type.FullName == LinqBinary)
{
return DbType.Binary;
}
return null;
}
///
/// Returns the prefix used to delimit parameters in SQL query strings.
///
///
///
public virtual string GetParameterPrefix(string connectionString)
{
return "@";
}
///
/// Converts a supplied C# object value into a value suitable for passing to the database
///
/// The value to convert
/// The converted value
public virtual object MapParameterValue(object value)
{
// Cast bools to integer
if (value is bool)
{
return ((bool)value) ? 1 : 0;
}
// Leave it
return value;
}
///
/// Called immediately before a command is executed, allowing for modification of the IDbCommand before it's passed to the database provider
///
///
public virtual void PreExecute(IDbCommand cmd)
{
}
///
/// Builds an SQL query suitable for performing page based queries to the database
///
/// The number of rows that should be skipped by the query
/// The number of rows that should be retruend by the query
/// The original SQL query after being parsed into it's component parts
/// Arguments to any embedded parameters in the SQL query
/// The final SQL query that should be executed.
public virtual string BuildPageQuery(long skip, long take, PagingHelper.SQLParts parts, ref object[] args)
{
var sql = string.Format("{0}\nLIMIT @{1} OFFSET @{2}", parts.sql, args.Length, args.Length + 1);
args = args.Concat(new object[] { take, skip }).ToArray();
return sql;
}
public virtual bool UseColumnAliases()
{
return false;
}
///
/// Returns an SQL Statement that can check for the existance of a row in the database.
///
///
public virtual string GetExistsSql()
{
return "SELECT COUNT(*) FROM {0} WHERE {1}";
}
///
/// Escape a tablename into a suitable format for the associated database provider.
///
/// The name of the table (as specified by the client program, or as attributes on the associated POCO class.
/// The escaped table name
public virtual string EscapeTableName(string tableName)
{
// Assume table names with "dot" are already escaped
return tableName.IndexOf('.') >= 0 ? tableName : EscapeSqlIdentifier(tableName);
}
///
/// Escape and arbitary SQL identifier into a format suitable for the associated database provider
///
/// The SQL identifier to be escaped
/// The escaped identifier
public virtual string EscapeSqlIdentifier(string str)
{
return string.Format("[{0}]", str);
}
///
/// Return an SQL expression that can be used to populate the primary key column of an auto-increment column.
///
/// Table info describing the table
/// An SQL expressions
/// See the Oracle database type for an example of how this method is used.
public virtual string GetAutoIncrementExpression(TableInfo ti)
{
return null;
}
///
/// Returns an SQL expression that can be used to specify the return value of auto incremented columns.
///
/// The primary key of the row being inserted.
/// An expression describing how to return the new primary key value
/// See the SQLServer database provider for an example of how this method is used.
public virtual string GetInsertOutputClause(string primaryKeyName)
{
return string.Empty;
}
///
/// Performs an Insert operation
///
/// The calling Database object
/// The insert command to be executed
/// The primary key of the table being inserted into
///
///
/// The ID of the newly inserted record
public virtual object ExecuteInsert(Database db, IDbCommand cmd, string primaryKeyName, T poco1, object[] args)
{
cmd.CommandText += ";\nSELECT @@IDENTITY AS NewID;";
return db.ExecuteScalarHelper(cmd);
}
public virtual void InsertBulk(IDatabase db, IEnumerable pocos)
{
foreach (var poco in pocos)
{
db.Insert(poco);
}
}
///
/// Look at the type and provider name being used and instantiate a suitable DatabaseType instance.
///
///
///
///
public static DatabaseType Resolve(string typeName, string providerName)
{
// Try using type name first (more reliable)
if (typeName.StartsWith("MySql"))
return Singleton.Instance;
if (typeName.StartsWith("SqlCe"))
return Singleton.Instance;
if (typeName.StartsWith("Npgsql") || typeName.StartsWith("PgSql"))
return Singleton.Instance;
if (typeName.StartsWith("OracleManaged"))
return Singleton.Instance;
if (typeName.StartsWith("Oracle"))
return Singleton.Instance;
if (typeName.StartsWith("SQLite"))
return Singleton.Instance;
if (typeName.StartsWith("SqlConnection"))
return Singleton.Instance;
if (typeName.StartsWith("Fb") || typeName.StartsWith("Firebird"))
return Singleton.Instance;
if (!string.IsNullOrEmpty(providerName))
{
// Try again with provider name
if (providerName.IndexOf("MySql", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton.Instance;
if (providerName.IndexOf("SqlServerCe", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton.Instance;
if (providerName.IndexOf("pgsql", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton.Instance;
if (providerName.IndexOf("Oracle.DataAccess", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton.Instance;
if (providerName.IndexOf("Oracle.ManagedDataAccess", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton.Instance;
if (providerName.IndexOf("SQLite", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton.Instance;
if (providerName.IndexOf("Firebird", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton.Instance;
}
// Assume SQL Server
return Singleton.Instance;
}
public virtual string GetDefaultInsertSql(string tableName, string[] names, string[] parameters)
{
return string.Format("INSERT INTO {0} DEFAULT VALUES", EscapeTableName(tableName));
}
public virtual IsolationLevel GetDefaultTransactionIsolationLevel()
{
return IsolationLevel.ReadCommitted;
}
public virtual string GetSQLForTransactionLevel(IsolationLevel isolationLevel)
{
switch (isolationLevel)
{
case IsolationLevel.ReadCommitted:
return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED;";
case IsolationLevel.ReadUncommitted:
return "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;";
case IsolationLevel.RepeatableRead:
return "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;";
case IsolationLevel.Serializable:
return "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;";
case IsolationLevel.Snapshot:
return "SET TRANSACTION ISOLATION LEVEL SNAPSHOT;";
default:
return "SET TRANSACTION ISOLATION LEVEL READ COMMITTED;";
}
}
public SqlExpression ExpressionVisitor(IDatabase db)
{
return ExpressionVisitor(db, false);
}
public virtual SqlExpression ExpressionVisitor(IDatabase db, bool prefixTableName)
{
return new DefaultSqlExpression(db, prefixTableName);
}
public virtual string GetProviderName()
{
return "System.Data.SqlClient";
}
}
}
一键复制
编辑
Web IDE
原始数据
按行查看
历史