Commit b67d6850 authored by jedidja's avatar jedidja

Derived SqlCompactDatabase from Database

Changed CreateTableConstructor to work for child table type
parent 5e8051e1
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}</ProjectGuid> <ProjectGuid>{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dapper.Rainbow</RootNamespace> <RootNamespace>Dapper.Rainbow</RootNamespace>
<AssemblyName>Dapper.Rainbow</AssemblyName> <AssemblyName>Dapper.Rainbow</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<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" />
</ItemGroup> <Compile Include="SqlCompactDatabase.cs" />
<ItemGroup> </ItemGroup>
<ProjectReference Include="..\Dapper\Dapper.csproj"> <ItemGroup>
<Project>{DAF737E1-05B5-4189-A5AA-DAC6233B64D7}</Project> <ProjectReference Include="..\Dapper\Dapper.csproj">
<Name>Dapper</Name> <Project>{DAF737E1-05B5-4189-A5AA-DAC6233B64D7}</Project>
</ProjectReference> <Name>Dapper</Name>
</ItemGroup> </ProjectReference>
<ItemGroup> </ItemGroup>
<None Include="Dapper.Rainbow.nuspec"> <ItemGroup>
<SubType>Designer</SubType> <None Include="Dapper.Rainbow.nuspec">
</None> <SubType>Designer</SubType>
</ItemGroup> </None>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>
\ No newline at end of file
...@@ -25,10 +25,10 @@ namespace Dapper ...@@ -25,10 +25,10 @@ namespace Dapper
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>
{ {
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)
...@@ -176,52 +181,52 @@ public void RollbackTransaction() ...@@ -176,52 +181,52 @@ public void RollbackTransaction()
{ {
transaction.Rollback(); transaction.Rollback();
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
)); ));
foreach (var setter in setters) foreach (var setter in setters)
{ {
il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0);
// [db] // [db]
il.Emit(OpCodes.Ldstr, setter.Item3); il.Emit(OpCodes.Ldstr, setter.Item3);
// [db, likelyname] // [db, likelyname]
il.Emit(OpCodes.Newobj, setter.Item2); il.Emit(OpCodes.Newobj, setter.Item2);
// [table] // [table]
var table = il.DeclareLocal(setter.Item2.DeclaringType); var table = il.DeclareLocal(setter.Item2.DeclaringType);
il.Emit(OpCodes.Stloc, table); il.Emit(OpCodes.Stloc, table);
// [] // []
il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0);
// [db] // [db]
il.Emit(OpCodes.Castclass, setter.Item4); il.Emit(OpCodes.Castclass, setter.Item4);
// [db cast to container] // [db cast to container]
il.Emit(OpCodes.Ldloc, table); il.Emit(OpCodes.Ldloc, table);
// [db cast to container, table] // [db cast to container, table]
il.Emit(OpCodes.Callvirt, setter.Item1); il.Emit(OpCodes.Callvirt, setter.Item1);
// [] // []
} }
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