Commit 396863bf authored by Sam's avatar Sam

Merge pull request #30 from jedidja/b67d6850

SQL Compact 4 support
parents 5e8051e1 b67d6850
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
<Compile Include="Database.cs" /> <Compile Include="Database.cs" />
<Compile Include="Snapshotter.cs" /> <Compile Include="Snapshotter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SqlCompactDatabase.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Dapper\Dapper.csproj"> <ProjectReference Include="..\Dapper\Dapper.csproj">
......
...@@ -26,9 +26,9 @@ public abstract class Database<TDatabase> : IDisposable where TDatabase : Databa ...@@ -26,9 +26,9 @@ public abstract class Database<TDatabase> : IDisposable where TDatabase : Databa
{ {
public class Table<T> public class Table<T>
{ {
Database<TDatabase> database; internal Database<TDatabase> database;
string tableName; internal string tableName;
string likelyTableName; internal string likelyTableName;
public Table(Database<TDatabase> database, string likelyTableName) public Table(Database<TDatabase> database, string likelyTableName)
{ {
...@@ -50,7 +50,7 @@ public string TableName ...@@ -50,7 +50,7 @@ public string TableName
/// </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 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);
...@@ -114,7 +114,7 @@ public IEnumerable<T> All() ...@@ -114,7 +114,7 @@ public IEnumerable<T> All()
} }
static ConcurrentDictionary<Type, List<string>> paramNameCache = new ConcurrentDictionary<Type, List<string>>(); static ConcurrentDictionary<Type, List<string>> paramNameCache = new ConcurrentDictionary<Type, List<string>>();
private static List<string> GetParamNames(object o) internal static List<string> GetParamNames(object o)
{ {
if (o is DynamicParameters) if (o is DynamicParameters)
{ {
...@@ -147,18 +147,23 @@ public static TDatabase Init(DbConnection connection, int commandTimeout) ...@@ -147,18 +147,23 @@ public static TDatabase Init(DbConnection connection, int commandTimeout)
return db; return db;
} }
private static Action<Database<TDatabase>> tableConstructor; internal static Action<TDatabase> tableConstructor;
private void InitDatabase(DbConnection connection, int commandTimeout) internal void InitDatabase(DbConnection connection, int commandTimeout)
{ {
this.connection = connection; this.connection = connection;
this.commandTimeout = commandTimeout; this.commandTimeout = commandTimeout;
if (tableConstructor == null) if (tableConstructor == null)
{ {
tableConstructor = CreateTableConstructor(); tableConstructor = CreateTableConstructorForTable();
} }
tableConstructor(this); tableConstructor(this as TDatabase);
}
internal virtual Action<TDatabase> CreateTableConstructorForTable()
{
return CreateTableConstructor(typeof(Table<>));
} }
public void BeginTransaction(IsolationLevel isolation = IsolationLevel.ReadCommitted) public void BeginTransaction(IsolationLevel isolation = IsolationLevel.ReadCommitted)
...@@ -178,16 +183,16 @@ public void RollbackTransaction() ...@@ -178,16 +183,16 @@ public void RollbackTransaction()
transaction = null; transaction = null;
} }
protected Action<Database<TDatabase>> CreateTableConstructor() protected Action<TDatabase> CreateTableConstructor(Type tableType)
{ {
var dm = new DynamicMethod("ConstructInstances", null, new Type[] { typeof(Database<TDatabase>) }, true); var dm = new DynamicMethod("ConstructInstances", null, new Type[] { typeof(TDatabase) }, true);
var il = dm.GetILGenerator(); var il = dm.GetILGenerator();
var setters = GetType().GetProperties() var setters = GetType().GetProperties()
.Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Table<>)) .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == tableType)
.Select(p => Tuple.Create( .Select(p => Tuple.Create(
p.GetSetMethod(true), p.GetSetMethod(true),
p.PropertyType.GetConstructor(new Type[] { typeof(Database<TDatabase>), typeof(string) }), p.PropertyType.GetConstructor(new Type[] { typeof(TDatabase), typeof(string) }),
p.Name, p.Name,
p.DeclaringType p.DeclaringType
)); ));
...@@ -221,7 +226,7 @@ protected Action<Database<TDatabase>> CreateTableConstructor() ...@@ -221,7 +226,7 @@ protected Action<Database<TDatabase>> CreateTableConstructor()
} }
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
return (Action<Database<TDatabase>>)dm.CreateDelegate(typeof(Action<Database<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>();
......
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
namespace Dapper.Rainbow
{
public abstract class SqlCompactDatabase<TDatabase> : Database<TDatabase>, IDisposable where TDatabase : Database<TDatabase>, new()
{
public class SqlCompactTable<T> : Table<T>
{
public SqlCompactTable(Database<TDatabase> database, string likelyTableName)
: base(database, likelyTableName)
{
}
/// <summary>
/// Insert a row into the db
/// </summary>
/// <param name="data">Either DynamicParameters or an anonymous type or concrete type</param>
/// <returns></returns>
public override int? Insert(dynamic data)
{
var o = (object)data;
List<string> paramNames = GetParamNames(o);
paramNames.Remove("Id");
string cols = string.Join(",", paramNames);
string cols_params = string.Join(",", paramNames.Select(p => "@" + p));
var sql = "insert " + TableName + " (" + cols + ") values (" + cols_params + ")";
if (database.Execute(sql, o) != 1)
{
return null;
}
return (int)database.Query<decimal>("SELECT @@IDENTITY AS LastInsertedId").Single();
}
}
public static TDatabase Init(DbConnection connection)
{
TDatabase db = new TDatabase();
db.InitDatabase(connection, 0);
return db;
}
internal override Action<TDatabase> CreateTableConstructorForTable()
{
return CreateTableConstructor(typeof(SqlCompactTable<>));
}
}
}
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