Commit c9160c13 authored by Sam Saffron's avatar Sam Saffron

Upped dapper to 1.8

Broke SqlBuilder to another assembly
Added Dapper.Rainbow (minimal ORM)
Changed nuget to distribute DLLs
parent 4d1d028b
......@@ -8,8 +8,8 @@
<ProjectGuid>{B26305D8-3A89-4D68-A981-9BBF378B81FA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dapper_NET35</RootNamespace>
<AssemblyName>Dapper NET35</AssemblyName>
<RootNamespace>Dapper</RootNamespace>
<AssemblyName>Dapper</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
......
......@@ -65,6 +65,10 @@
<Project>{C2FC4DF5-C8D1-4EA8-8E0C-85A3793EB0BB}</Project>
<Name>Dapper.Contrib</Name>
</ProjectReference>
<ProjectReference Include="..\Dapper.SqlBuilder\Dapper.SqlBuilder.csproj">
<Project>{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}</Project>
<Name>Dapper.SqlBuilder</Name>
</ProjectReference>
<ProjectReference Include="..\Dapper\Dapper.csproj">
<Project>{DAF737E1-05B5-4189-A5AA-DAC6233B64D7}</Project>
<Name>Dapper</Name>
......
......@@ -6,6 +6,7 @@
using Dapper.Contrib.Extensions;
using System.Collections.Generic;
using System;
using Dapper;
namespace Dapper.Contrib.Tests
......
......@@ -440,155 +440,4 @@ public class KeyAttribute : Attribute
{
}
public class SqlBuilder
{
Dictionary<string, Clauses> data = new Dictionary<string, Clauses>();
int seq;
class Clause
{
public string Sql { get; set; }
public object Parameters { get; set; }
}
class Clauses : List<Clause>
{
string joiner;
string prefix;
string postfix;
public Clauses(string joiner, string prefix = "", string postfix = "")
{
this.joiner = joiner;
this.prefix = prefix;
this.postfix = postfix;
}
public string ResolveClauses(DynamicParameters p)
{
foreach (var item in this)
{
p.AddDynamicParams(item.Parameters);
}
return prefix + string.Join(joiner, this.Select(c => c.Sql)) + postfix;
}
}
public class Template
{
readonly string sql;
readonly SqlBuilder builder;
readonly object initParams;
int dataSeq = -1; // Unresolved
public Template(SqlBuilder builder, string sql, dynamic parameters)
{
this.initParams = parameters;
this.sql = sql;
this.builder = builder;
}
static System.Text.RegularExpressions.Regex regex =
new System.Text.RegularExpressions.Regex(@"\/\*\*.+\*\*\/", System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline);
void ResolveSql()
{
if (dataSeq != builder.seq)
{
DynamicParameters p = new DynamicParameters(initParams);
rawSql = sql;
foreach (var pair in builder.data)
{
rawSql = rawSql.Replace("/**" + pair.Key + "**/", pair.Value.ResolveClauses(p));
}
parameters = p;
// replace all that is left with empty
rawSql = regex.Replace(rawSql, "");
dataSeq = builder.seq;
}
}
string rawSql;
object parameters;
public string RawSql { get { ResolveSql(); return rawSql; } }
public object Parameters { get { ResolveSql(); return parameters; } }
}
public SqlBuilder()
{
}
public Template AddTemplate(string sql, dynamic parameters = null)
{
return new Template(this, sql, parameters);
}
void AddClause(string name, string sql, object parameters, string joiner, string prefix = "", string postfix = "")
{
Clauses clauses;
if (!data.TryGetValue(name, out clauses))
{
clauses = new Clauses(joiner, prefix, postfix);
data[name] = clauses;
}
clauses.Add(new Clause { Sql = sql, Parameters = parameters });
seq++;
}
public SqlBuilder LeftJoin(string sql, dynamic parameters = null)
{
AddClause("leftjoin", sql, parameters, joiner: "\nLEFT JOIN ", prefix: "\nLEFT JOIN ", postfix: "\n");
return this;
}
public SqlBuilder Where(string sql, dynamic parameters = null)
{
AddClause("where", sql, parameters, " AND ", prefix: "WHERE ", postfix: "\n");
return this;
}
public SqlBuilder OrderBy(string sql, dynamic parameters = null)
{
AddClause("orderby", sql, parameters, " , ", prefix: "ORDER BY ", postfix: "\n");
return this;
}
public SqlBuilder Select(string sql, dynamic parameters = null)
{
AddClause("select", sql, parameters, " , ", prefix: "", postfix: "\n");
return this;
}
public SqlBuilder AddParameters(dynamic parameters)
{
AddClause("--parameters", "", parameters, "");
return this;
}
public SqlBuilder Join(string sql, dynamic parameters = null)
{
AddClause("join", sql, parameters, joiner: "\nJOIN ", prefix: "\nJOIN ", postfix: "\n");
return this;
}
public SqlBuilder GroupBy(string sql, dynamic parameters = null)
{
AddClause("groupby", sql, parameters, joiner: " , ", prefix: "\nGROUP BY ", postfix: "\n");
return this;
}
public SqlBuilder Having(string sql, dynamic parameters = null)
{
AddClause("having", sql, parameters, joiner: "\nAND ", prefix: "HAVING ", postfix: "\n");
return this;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dapper.Rainbow</RootNamespace>
<AssemblyName>Dapper.Rainbow</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Database.cs" />
<Compile Include="Snapshotter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Dapper\Dapper.csproj">
<Project>{DAF737E1-05B5-4189-A5AA-DAC6233B64D7}</Project>
<Name>Dapper</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using Dapper;
using System.Collections.Concurrent;
using System.Reflection;
using System.Text;
using System.Data.Common;
using System.Diagnostics;
using System.Reflection.Emit;
namespace Dapper
{
/// <summary>
/// A container for a database, assumes all the tables have an Id column named Id
/// </summary>
/// <typeparam name="TDatabase"></typeparam>
public abstract class Database<TDatabase> : IDisposable where TDatabase : Database<TDatabase>, new()
{
public class Table<T>
{
Database<TDatabase> database;
string tableName;
string likelyTableName;
public Table(Database<TDatabase> database, string likelyTableName)
{
this.database = database;
this.likelyTableName = likelyTableName;
}
public string TableName
{
get
{
tableName = tableName ?? database.DetermineTableName<T>(likelyTableName);
return tableName;
}
}
/// <summary>
/// Insert a row into the db
/// </summary>
/// <param name="data">Either DynamicParameters or an anonymous type or concrete type</param>
/// <returns></returns>
public int? Insert(dynamic data)
{
var o = (object)data;
List<string> paramNames = GetParamNames(o);
string cols = string.Join(",", paramNames);
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)";
return database.Query<int?>(sql, o).Single();
}
/// <summary>
/// Update a record in the DB
/// </summary>
/// <param name="id"></param>
/// <param name="data"></param>
/// <returns></returns>
public int Update(int id, dynamic data)
{
List<string> paramNames = GetParamNames(data);
var builder = new StringBuilder();
builder.Append("update [").Append(TableName).Append("] set ");
builder.AppendLine(string.Join(",", paramNames.Where(n => n != "Id").Select(p => p + "= @" + p)));
builder.Append("where Id = @Id");
DynamicParameters parameters = new DynamicParameters(data);
parameters.Add("Id", id);
return database.Execute(builder.ToString(), parameters);
}
/// <summary>
/// Delete a record for the DB
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public bool Delete(int id)
{
return database.Execute("delete " + TableName + " where Id = @id", new { id }) > 0;
}
/// <summary>
/// Grab a record with a particular Id from the DB
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public T Get(int id)
{
return database.Query<T>("select * from " + TableName + " where id = @id", new { id }).FirstOrDefault();
}
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>>();
private 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 Create(DbConnection connection, int commandTimeout)
{
TDatabase db = new TDatabase();
db.InitDatabase(connection, commandTimeout);
return db;
}
private static Action<Database<TDatabase>> tableConstructor;
private void InitDatabase(DbConnection connection, int commandTimeout)
{
this.connection = connection;
this.commandTimeout = commandTimeout;
if (tableConstructor == null)
{
tableConstructor = CreateTableConstructor();
}
tableConstructor(this);
}
public void BeginTransaction(IsolationLevel isolation = IsolationLevel.ReadCommitted)
{
transaction = connection.BeginTransaction(isolation);
}
public void CommitTransaction()
{
transaction.Commit();
transaction = null;
}
public void RollbackTransaction()
{
transaction.Rollback();
transaction = null;
}
public Action<Database<TDatabase>> CreateTableConstructor()
{
var dm = new DynamicMethod("ConstructInstances", null, new Type[] { typeof(Database<TDatabase>) }, true);
var il = dm.GetILGenerator();
var setters = GetType().GetProperties()
.Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Table<>))
.Select(p => Tuple.Create(
p.GetSetMethod(true),
p.PropertyType.GetConstructor(new Type[] { typeof(Database<TDatabase>), typeof(string) }),
p.Name,
p.DeclaringType
));
foreach (var setter in setters)
{
il.Emit(OpCodes.Ldarg_0);
// [db]
il.Emit(OpCodes.Ldstr, setter.Item3);
// [db, likelyname]
il.Emit(OpCodes.Newobj, setter.Item2);
// [table]
var table = il.DeclareLocal(setter.Item2.DeclaringType);
il.Emit(OpCodes.Stloc, table);
// []
il.Emit(OpCodes.Ldarg_0);
// [db]
il.Emit(OpCodes.Castclass, setter.Item4);
// [db cast to container]
il.Emit(OpCodes.Ldloc, table);
// [db cast to container, table]
il.Emit(OpCodes.Callvirt, setter.Item1);
// []
}
il.Emit(OpCodes.Ret);
return (Action<Database<TDatabase>>)dm.CreateDelegate(typeof(Action<Database<TDatabase>>));
}
static ConcurrentDictionary<Type, string> tableNameMap = new ConcurrentDictionary<Type, string>();
private string DetermineTableName<T>(string likelyTableName)
{
string name;
if (!tableNameMap.TryGetValue(typeof(T), out name))
{
name = likelyTableName;
if (!TableExists(name))
{
name = typeof(T).Name;
}
tableNameMap[typeof(T)] = name;
}
return 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;
}
public int Execute(string sql, dynamic param = null)
{
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)
{
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)
{
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)
{
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)
{
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)
{
return SqlMapper.Query(connection, sql, map, param as object, transaction, buffered, splitOn);
}
public IEnumerable<dynamic> Query(string sql, dynamic param = null, bool buffered = true)
{
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)
{
return SqlMapper.QueryMultiple(connection, sql, param, transaction, commandTimeout, commandType);
}
public void Dispose()
{
if (connection.State != ConnectionState.Closed)
{
if (transaction != null)
{
transaction.Rollback();
}
connection.Close();
connection = null;
}
}
}
}
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Dapper.Rainbow")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Dapper.Rainbow")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("e763c106-eef4-4654-afcc-c28fded057e5")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Reflection.Emit;
namespace Dapper
{
public static class Snapshotter
{
public static Snapshot<T> Start<T>(T obj)
{
return new Snapshot<T>(obj);
}
public class Snapshot<T>
{
static Func<T, T> cloner;
static Func<T, T, List<Change>> differ;
T memberWiseClone;
T trackedObject;
public Snapshot(T original)
{
memberWiseClone = Clone(original);
trackedObject = original;
}
public class Change
{
public string Name { get; set; }
public object NewValue { get; set; }
}
public DynamicParameters Diff()
{
return Diff(memberWiseClone, trackedObject);
}
private static T Clone(T myObject)
{
cloner = cloner ?? GenerateCloner();
return cloner(myObject);
}
private static DynamicParameters Diff(T original, T current)
{
var dm = new DynamicParameters();
differ = differ ?? GenerateDiffer();
foreach (var pair in differ(original, current))
{
dm.Add(pair.Name, pair.NewValue);
}
return dm;
}
static List<PropertyInfo> RelevantProperties()
{
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p =>
p.GetSetMethod() != null &&
p.GetGetMethod() != null &&
(p.PropertyType.IsValueType ||
p.PropertyType == typeof(string) ||
(p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
).ToList();
}
private static bool AreEqual<U>(U first, U second)
{
if (first == null && second == null) return true;
if (first == null && second != null) return false;
return first.Equals(second);
}
private static Func<T, T, List<Change>> GenerateDiffer()
{
var dm = new DynamicMethod("DoDiff", typeof(List<Change>), new Type[] { typeof(T), typeof(T) }, true);
var il = dm.GetILGenerator();
// change list
il.DeclareLocal(typeof(List<Change>));
il.DeclareLocal(typeof(Change));
il.DeclareLocal(typeof(object)); // boxed change
il.Emit(OpCodes.Newobj, typeof(List<Change>).GetConstructor(Type.EmptyTypes));
// [list]
il.Emit(OpCodes.Stloc_0);
foreach (var prop in RelevantProperties())
{
// []
il.Emit(OpCodes.Ldarg_0);
// [original]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod());
// [original prop val]
il.Emit(OpCodes.Ldarg_1);
// [original prop val, current]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod());
// [original prop val, current prop val]
il.Emit(OpCodes.Dup);
// [original prop val, current prop val, current prop val]
if (prop.PropertyType != typeof(string))
{
il.Emit(OpCodes.Box, prop.PropertyType);
// [original prop val, current prop val, current prop val boxed]
}
il.Emit(OpCodes.Stloc_2);
// [original prop val, current prop val]
il.EmitCall(OpCodes.Call, typeof(Snapshot<T>).GetMethod("AreEqual", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(new Type[] { prop.PropertyType }), null);
// [result]
Label skip = il.DefineLabel();
il.Emit(OpCodes.Brtrue_S, skip);
// []
il.Emit(OpCodes.Newobj, typeof(Change).GetConstructor(Type.EmptyTypes));
// [change]
il.Emit(OpCodes.Dup);
// [change,change]
il.Emit(OpCodes.Stloc_1);
// [change]
il.Emit(OpCodes.Ldstr, prop.Name);
// [change, name]
il.Emit(OpCodes.Callvirt, typeof(Change).GetMethod("set_Name"));
// []
il.Emit(OpCodes.Ldloc_1);
// [change]
il.Emit(OpCodes.Ldloc_2);
// [change, boxed]
il.Emit(OpCodes.Callvirt, typeof(Change).GetMethod("set_NewValue"));
// []
il.Emit(OpCodes.Ldloc_0);
// [change list]
il.Emit(OpCodes.Ldloc_1);
// [change list, change]
il.Emit(OpCodes.Callvirt, typeof(List<Change>).GetMethod("Add"));
// []
il.MarkLabel(skip);
}
il.Emit(OpCodes.Ldloc_0);
// [change list]
il.Emit(OpCodes.Ret);
return (Func<T, T, List<Change>>)dm.CreateDelegate(typeof(Func<T, T, List<Change>>));
}
// adapted from http://stackoverflow.com/a/966466/17174
private static Func<T, T> GenerateCloner()
{
Delegate myExec = null;
var dm = new DynamicMethod("DoClone", typeof(T), new Type[] { typeof(T) }, true);
var ctor = typeof(T).GetConstructor(new Type[] { });
var il = dm.GetILGenerator();
il.DeclareLocal(typeof(T));
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_0);
foreach (var prop in RelevantProperties())
{
il.Emit(OpCodes.Ldloc_0);
// [clone]
il.Emit(OpCodes.Ldarg_0);
// [clone, source]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod());
// [clone, source val]
il.Emit(OpCodes.Callvirt, prop.GetSetMethod());
// []
}
// Load new constructed obj on eval stack -> 1 item on stack
il.Emit(OpCodes.Ldloc_0);
// Return constructed object. --> 0 items on stack
il.Emit(OpCodes.Ret);
myExec = dm.CreateDelegate(typeof(Func<T, T>));
return (Func<T, T>)myExec;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dapper.SqlBuilder</RootNamespace>
<AssemblyName>Dapper.SqlBuilder</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="SqlBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Dapper\Dapper.csproj">
<Project>{DAF737E1-05B5-4189-A5AA-DAC6233B64D7}</Project>
<Name>Dapper</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Dapper.SqlBuilder")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Dapper.SqlBuilder")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("27491c26-c95d-44e5-b907-30559ef11265")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Dapper
{
public class SqlBuilder
{
Dictionary<string, Clauses> data = new Dictionary<string, Clauses>();
int seq;
class Clause
{
public string Sql { get; set; }
public object Parameters { get; set; }
}
class Clauses : List<Clause>
{
string joiner;
string prefix;
string postfix;
public Clauses(string joiner, string prefix = "", string postfix = "")
{
this.joiner = joiner;
this.prefix = prefix;
this.postfix = postfix;
}
public string ResolveClauses(DynamicParameters p)
{
foreach (var item in this)
{
p.AddDynamicParams(item.Parameters);
}
return prefix + string.Join(joiner, this.Select(c => c.Sql)) + postfix;
}
}
public class Template
{
readonly string sql;
readonly SqlBuilder builder;
readonly object initParams;
int dataSeq = -1; // Unresolved
public Template(SqlBuilder builder, string sql, dynamic parameters)
{
this.initParams = parameters;
this.sql = sql;
this.builder = builder;
}
static System.Text.RegularExpressions.Regex regex =
new System.Text.RegularExpressions.Regex(@"\/\*\*.+\*\*\/", System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline);
void ResolveSql()
{
if (dataSeq != builder.seq)
{
DynamicParameters p = new DynamicParameters(initParams);
rawSql = sql;
foreach (var pair in builder.data)
{
rawSql = rawSql.Replace("/**" + pair.Key + "**/", pair.Value.ResolveClauses(p));
}
parameters = p;
// replace all that is left with empty
rawSql = regex.Replace(rawSql, "");
dataSeq = builder.seq;
}
}
string rawSql;
object parameters;
public string RawSql { get { ResolveSql(); return rawSql; } }
public object Parameters { get { ResolveSql(); return parameters; } }
}
public SqlBuilder()
{
}
public Template AddTemplate(string sql, dynamic parameters = null)
{
return new Template(this, sql, parameters);
}
void AddClause(string name, string sql, object parameters, string joiner, string prefix = "", string postfix = "")
{
Clauses clauses;
if (!data.TryGetValue(name, out clauses))
{
clauses = new Clauses(joiner, prefix, postfix);
data[name] = clauses;
}
clauses.Add(new Clause { Sql = sql, Parameters = parameters });
seq++;
}
public SqlBuilder LeftJoin(string sql, dynamic parameters = null)
{
AddClause("leftjoin", sql, parameters, joiner: "\nLEFT JOIN ", prefix: "\nLEFT JOIN ", postfix: "\n");
return this;
}
public SqlBuilder Where(string sql, dynamic parameters = null)
{
AddClause("where", sql, parameters, " AND ", prefix: "WHERE ", postfix: "\n");
return this;
}
public SqlBuilder OrderBy(string sql, dynamic parameters = null)
{
AddClause("orderby", sql, parameters, " , ", prefix: "ORDER BY ", postfix: "\n");
return this;
}
public SqlBuilder Select(string sql, dynamic parameters = null)
{
AddClause("select", sql, parameters, " , ", prefix: "", postfix: "\n");
return this;
}
public SqlBuilder AddParameters(dynamic parameters)
{
AddClause("--parameters", "", parameters, "");
return this;
}
public SqlBuilder Join(string sql, dynamic parameters = null)
{
AddClause("join", sql, parameters, joiner: "\nJOIN ", prefix: "\nJOIN ", postfix: "\n");
return this;
}
public SqlBuilder GroupBy(string sql, dynamic parameters = null)
{
AddClause("groupby", sql, parameters, joiner: " , ", prefix: "\nGROUP BY ", postfix: "\n");
return this;
}
public SqlBuilder Having(string sql, dynamic parameters = null)
{
AddClause("having", sql, parameters, joiner: "\nAND ", prefix: "HAVING ", postfix: "\n");
return this;
}
}
}
......@@ -13,6 +13,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.Contrib.Tests", "Dap
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DapperTests NET35", "DapperTests NET35\DapperTests NET35.csproj", "{3BAA9F79-BA0A-4092-B47B-20170DD47989}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.SqlBuilder", "Dapper.SqlBuilder\Dapper.SqlBuilder.csproj", "{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.Rainbow", "Dapper.Rainbow\Dapper.Rainbow.csproj", "{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -83,6 +87,26 @@ Global
{3BAA9F79-BA0A-4092-B47B-20170DD47989}.Release|Mixed Platforms.Build.0 = Release|x86
{3BAA9F79-BA0A-4092-B47B-20170DD47989}.Release|x86.ActiveCfg = Release|x86
{3BAA9F79-BA0A-4092-B47B-20170DD47989}.Release|x86.Build.0 = Release|x86
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Debug|x86.ActiveCfg = Debug|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Release|Any CPU.Build.0 = Release|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}.Release|x86.ActiveCfg = Release|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Debug|x86.ActiveCfg = Debug|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Release|Any CPU.Build.0 = Release|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{21BC6EA8-3D10-4CC9-A1B3-9FAD59F7D1BB}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
......@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.6.0.0")]
[assembly: AssemblyFileVersion("1.6.0.0")]
[assembly: AssemblyVersion("1.8.0.0")]
[assembly: AssemblyFileVersion("1.8.0.0")]
......@@ -2100,6 +2100,18 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Id
}
}
/// <summary>
/// All the names of the param in the bag, use Get to yank them out
/// </summary>
public IEnumerable<string> ParameterNames
{
get
{
return parameters.Select(p => p.Key);
}
}
/// <summary>
/// Get the value of a parameter
/// </summary>
......
......@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata schemaVersion="2">
<id>Dapper</id>
<version>1.7</version>
<version>1.8</version>
<title>Dapper dot net</title>
<authors>Sam Saffron,Marc Gravell</authors>
<owners>Sam Saffron,Marc Gravell</owners>
......@@ -11,15 +11,24 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A high performance Micro-ORM supporting Sql Server, MySQL, Sqlite, SqlCE, Firebird etc..</description>
<summary>A high performance Micro-ORM</summary>
<tags>orm,sql,micro-orm</tags>
<tags>orm sql micro-orm</tags>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Core" targetFramework=".NETFramework4.0-Client, .NETFramework4.0" />
<frameworkAssembly assemblyName="System" targetFramework=".NETFramework4.0-Client, .NETFramework4.0" />
<frameworkAssembly assemblyName="System.Data" targetFramework=".NETFramework4.0-Client, .NETFramework4.0" />
<frameworkAssembly assemblyName="System.Core"/>
<frameworkAssembly assemblyName="System"/>
<frameworkAssembly assemblyName="System.Data"/>
<frameworkAssembly assemblyName="Microsoft.CSharp" targetFramework=".NETFramework4.0-Client, .NETFramework4.0" />
</frameworkAssemblies>
<releaseNotes>
* 1.8 - Started release notes
* Important: Dapper is now shipping as a DLL which will work on .net 3.5 or .net 4.0,
* This improves the debugging experience as you no longer break into dapper when SQL fails.
* Added: ParameterNames on DynamicParameters
</releaseNotes>
</metadata>
<files>
<file src="SqlMapper.cs" target="content\Dapper\SqlMapper.cs" />
<file src="bin\Release\Dapper.dll" target="lib\net40" />
<file src="bin\Release\Dapper.pdb" target="lib\net40" />
<file src="..\Dapper NET35\bin\Release\Dapper.dll" target="lib\net35" />
<file src="..\Dapper NET35\bin\Release\Dapper.pdb" target="lib\net35" />
</files>
</package>
\ 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