Commit 4a7e7fb5 authored by Marc Gravell's avatar Marc Gravell

Merge branch 'master' of https://github.com/jedidja/dapper-dot-net into jedidja-master

Conflicts:
	Dapper.Rainbow/Database.cs
parents 4a9f0500 7919913c
/* /*
License: http://www.apache.org/licenses/LICENSE-2.0 License: http://www.apache.org/licenses/LICENSE-2.0
Home page: http://code.google.com/p/dapper-dot-net/ Home page: http://code.google.com/p/dapper-dot-net/
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Web; using System.Web;
using System.Data; using System.Data;
using Dapper; using Dapper;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Data.Common; using System.Data.Common;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection.Emit; using System.Reflection.Emit;
namespace Dapper namespace Dapper
{ {
/// <summary> /// <summary>
/// A container for a database, assumes all the tables have an Id column named Id /// A container for a database, assumes all the tables have an Id column named Id
/// </summary> /// </summary>
/// <typeparam name="TDatabase"></typeparam> /// <typeparam name="TDatabase"></typeparam>
public abstract class Database<TDatabase> : IDisposable where TDatabase : Database<TDatabase>, new() public abstract class Database<TDatabase> : IDisposable where TDatabase : Database<TDatabase>, new()
{ {
public class Table<T> public class Table<T>
{ {
internal Database<TDatabase> database; internal Database<TDatabase> database;
internal string tableName; internal string tableName;
internal string likelyTableName; internal string likelyTableName;
public Table(Database<TDatabase> database, string likelyTableName) public Table(Database<TDatabase> database, string likelyTableName)
{ {
this.database = database; this.database = database;
this.likelyTableName = likelyTableName; this.likelyTableName = likelyTableName;
} }
public string TableName public string TableName
{ {
get get
{ {
tableName = tableName ?? database.DetermineTableName<T>(likelyTableName); tableName = tableName ?? database.DetermineTableName<T>(likelyTableName);
return tableName; return tableName;
} }
} }
/// <summary> /// <summary>
/// Insert a row into the db /// Insert a row into the db
/// </summary> /// </summary>
/// <param name="data">Either DynamicParameters or an anonymous type or concrete type</param> /// <param name="data">Either DynamicParameters or an anonymous type or concrete type</param>
/// <returns></returns> /// <returns></returns>
public virtual int? Insert(dynamic data) public virtual int? Insert(dynamic data)
{ {
var o = (object)data; var o = (object)data;
List<string> paramNames = GetParamNames(o); List<string> paramNames = GetParamNames(o);
string cols = string.Join(",", paramNames); string cols = string.Join(",", paramNames);
string cols_params = string.Join(",", paramNames.Select(p => "@" + p)); string cols_params = string.Join(",", paramNames.Select(p => "@" + p));
var sql = "set nocount on insert " + TableName + " (" + cols + ") values (" + cols_params + ") select cast(scope_identity() as int)"; var sql = "set nocount on insert " + TableName + " (" + cols + ") values (" + cols_params + ") select cast(scope_identity() as int)";
return database.Query<int?>(sql, o).Single(); return database.Query<int?>(sql, o).Single();
} }
/// <summary> /// <summary>
/// Update a record in the DB /// Update a record in the DB
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <param name="data"></param> /// <param name="data"></param>
/// <returns></returns> /// <returns></returns>
public int Update(int id, dynamic data) public int Update(int id, dynamic data)
{ {
List<string> paramNames = GetParamNames((object)data); List<string> paramNames = GetParamNames((object)data);
var builder = new StringBuilder(); var builder = new StringBuilder();
builder.Append("update [").Append(TableName).Append("] set "); builder.Append("update [").Append(TableName).Append("] set ");
builder.AppendLine(string.Join(",", paramNames.Where(n => n != "Id").Select(p => p + "= @" + p))); builder.AppendLine(string.Join(",", paramNames.Where(n => n != "Id").Select(p => p + "= @" + p)));
builder.Append("where Id = @Id"); builder.Append("where Id = @Id");
DynamicParameters parameters = new DynamicParameters(data); DynamicParameters parameters = new DynamicParameters(data);
parameters.Add("Id", id); parameters.Add("Id", id);
return database.Execute(builder.ToString(), parameters); return database.Execute(builder.ToString(), parameters);
} }
/// <summary> /// <summary>
/// Delete a record for the DB /// Delete a record for the DB
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public bool Delete(int id) public bool Delete(int id)
{ {
return database.Execute("delete " + TableName + " where Id = @id", new { id }) > 0; return database.Execute("delete " + TableName + " where Id = @id", new { id }) > 0;
} }
/// <summary> /// <summary>
/// Grab a record with a particular Id from the DB /// Grab a record with a particular Id from the DB
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
public T Get(int id) public T Get(int id)
{ {
return database.Query<T>("select * from " + TableName + " where Id = @id", new { id }).FirstOrDefault(); return database.Query<T>("select * from " + TableName + " where Id = @id", new { id }).FirstOrDefault();
} }
public T First() public T First()
{
return database.Query<T>("select top 1 * from " + TableName).FirstOrDefault();
}
public IEnumerable<T> All()
{
return database.Query<T>("select * from " + TableName);
}
static ConcurrentDictionary<Type, List<string>> paramNameCache = new ConcurrentDictionary<Type, List<string>>();
internal static List<string> GetParamNames(object o)
{
if (o is DynamicParameters)
{
return (o as DynamicParameters).ParameterNames.ToList();
}
List<string> paramNames;
if (!paramNameCache.TryGetValue(o.GetType(), out paramNames))
{
paramNames = new List<string>();
foreach (var prop in o.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public))
{
paramNames.Add(prop.Name);
}
paramNameCache[o.GetType()] = paramNames;
}
return paramNames;
}
}
DbConnection connection;
int commandTimeout;
DbTransaction transaction;
public static TDatabase Init(DbConnection connection, int commandTimeout)
{
TDatabase db = new TDatabase();
db.InitDatabase(connection, commandTimeout);
return db;
}
internal static Action<TDatabase> tableConstructor;
internal void InitDatabase(DbConnection connection, int commandTimeout)
{
this.connection = connection;
this.commandTimeout = commandTimeout;
if (tableConstructor == null)
{ {
tableConstructor = CreateTableConstructorForTable(); return database.Query<T>("select top 1 * from " + TableName).FirstOrDefault();
} }
tableConstructor(this as TDatabase); public IEnumerable<T> All()
{
return database.Query<T>("select * from " + TableName);
}
static ConcurrentDictionary<Type, List<string>> paramNameCache = new ConcurrentDictionary<Type, List<string>>();
internal static List<string> GetParamNames(object o)
{
if (o is DynamicParameters)
{
return (o as DynamicParameters).ParameterNames.ToList();
}
List<string> paramNames;
if (!paramNameCache.TryGetValue(o.GetType(), out paramNames))
{
paramNames = new List<string>();
foreach (var prop in o.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public))
{
paramNames.Add(prop.Name);
}
paramNameCache[o.GetType()] = paramNames;
}
return paramNames;
}
}
DbConnection connection;
int commandTimeout;
DbTransaction transaction;
public static TDatabase Init(DbConnection connection, int commandTimeout)
{
TDatabase db = new TDatabase();
db.InitDatabase(connection, commandTimeout);
return db;
}
internal static Action<TDatabase> tableConstructor;
internal void InitDatabase(DbConnection connection, int commandTimeout)
{
this.connection = connection;
this.commandTimeout = commandTimeout;
if (tableConstructor == null)
{
tableConstructor = CreateTableConstructorForTable();
}
tableConstructor(this as TDatabase);
} }
internal virtual Action<TDatabase> CreateTableConstructorForTable() internal virtual Action<TDatabase> CreateTableConstructorForTable()
{ {
return CreateTableConstructor(typeof(Table<>)); return CreateTableConstructor(typeof(Table<>));
} }
public void BeginTransaction(IsolationLevel isolation = IsolationLevel.ReadCommitted) public void BeginTransaction(IsolationLevel isolation = IsolationLevel.ReadCommitted)
{ {
transaction = connection.BeginTransaction(isolation); transaction = connection.BeginTransaction(isolation);
} }
public void CommitTransaction() public void CommitTransaction()
{ {
transaction.Commit(); transaction.Commit();
transaction = null; transaction = null;
} }
public void RollbackTransaction() public void RollbackTransaction()
{ {
transaction.Rollback(); transaction.Rollback();
transaction = null; transaction = null;
} }
protected Action<TDatabase> CreateTableConstructor(Type tableType) protected Action<TDatabase> CreateTableConstructor(Type tableType)
...@@ -227,84 +228,84 @@ protected Action<TDatabase> CreateTableConstructor(Type tableType) ...@@ -227,84 +228,84 @@ protected Action<TDatabase> CreateTableConstructor(Type tableType)
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
return (Action<TDatabase>)dm.CreateDelegate(typeof(Action<TDatabase>)); return (Action<TDatabase>)dm.CreateDelegate(typeof(Action<TDatabase>));
} }
static ConcurrentDictionary<Type, string> tableNameMap = new ConcurrentDictionary<Type, string>(); static ConcurrentDictionary<Type, string> tableNameMap = new ConcurrentDictionary<Type, string>();
private string DetermineTableName<T>(string likelyTableName) private string DetermineTableName<T>(string likelyTableName)
{ {
string name; string name;
if (!tableNameMap.TryGetValue(typeof(T), out name)) if (!tableNameMap.TryGetValue(typeof(T), out name))
{ {
name = likelyTableName; name = likelyTableName;
if (!TableExists(name)) if (!TableExists(name))
{ {
name = typeof(T).Name; name = typeof(T).Name;
} }
tableNameMap[typeof(T)] = name; tableNameMap[typeof(T)] = name;
} }
return name; return name;
} }
private bool TableExists(string name) private bool TableExists(string name)
{ {
return connection.Query("select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = @name", new { name }, transaction: transaction).Count() == 1; return connection.Query("select 1 from INFORMATION_SCHEMA.TABLES where TABLE_NAME = @name", new { name }, transaction: transaction).Count() == 1;
} }
public int Execute(string sql, dynamic param = null) public int Execute(string sql, dynamic param = null)
{ {
return SqlMapper.Execute(connection, sql, param as object, transaction, commandTimeout: this.commandTimeout); return SqlMapper.Execute(connection, sql, param as object, transaction, commandTimeout: this.commandTimeout);
} }
public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered = true) public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered = true)
{ {
return SqlMapper.Query<T>(connection, sql, param as object, transaction, buffered, commandTimeout); return SqlMapper.Query<T>(connection, sql, param as object, transaction, buffered, commandTimeout);
} }
public IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn); return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn);
} }
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn); return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn);
} }
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn); return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn);
} }
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn); return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn);
} }
public IEnumerable<dynamic> Query(string sql, dynamic param = null, bool buffered = true) public IEnumerable<dynamic> Query(string sql, dynamic param = null, bool buffered = true)
{ {
return SqlMapper.Query(connection, sql, param as object, transaction, buffered); return SqlMapper.Query(connection, sql, param as object, transaction, buffered);
} }
public Dapper.SqlMapper.GridReader QueryMultiple(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) public Dapper.SqlMapper.GridReader QueryMultiple(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
{ {
return SqlMapper.QueryMultiple(connection, sql, param, transaction, commandTimeout, commandType); return SqlMapper.QueryMultiple(connection, sql, param, transaction, commandTimeout, commandType);
} }
public void Dispose() public void Dispose()
{ {
if (connection.State != ConnectionState.Closed) if (connection.State != ConnectionState.Closed)
{ {
if (transaction != null) if (transaction != null)
{ {
transaction.Rollback(); transaction.Rollback();
} }
connection.Close(); connection.Close();
connection = null; connection = null;
} }
} }
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment