mirror of
https://github.com/DapperLib/Dapper.git
synced 2026-10-29 05:10:10 +08:00
Merge branch 'master' of https://github.com/SamSaffron/dapper-dot-net
Conflicts: Dapper.Contrib/SqlMapperExtensions.cs
This commit is contained in:
+6
-1
@@ -2,4 +2,9 @@
|
||||
bin/
|
||||
obj/
|
||||
/*.user
|
||||
_Resharper*
|
||||
_Resharper*
|
||||
.hgtags
|
||||
NuGet.exe
|
||||
*.user
|
||||
*.nupkg
|
||||
.docstats
|
||||
|
||||
@@ -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>
|
||||
@@ -36,7 +36,6 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Dapper\Properties\AssemblyInfo.cs">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -4,6 +4,9 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Dapper.Contrib.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Dapper;
|
||||
|
||||
|
||||
namespace Dapper.Contrib.Tests
|
||||
@@ -100,5 +103,52 @@ namespace Dapper.Contrib.Tests
|
||||
connection.Update(notrackedUser).IsEqualTo(false); //returns false, user not found
|
||||
}
|
||||
}
|
||||
|
||||
public void BuilderSelectClause()
|
||||
{
|
||||
using (var connection = GetOpenConnection())
|
||||
{
|
||||
var rand = new Random(8675309);
|
||||
var data = new List<User>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
var nU = new User { Age = rand.Next(70), Id = i, Name = Guid.NewGuid().ToString() };
|
||||
data.Add(nU);
|
||||
nU.Id = (int)connection.Insert<User>(nU);
|
||||
}
|
||||
|
||||
var builder = new SqlBuilder();
|
||||
var justId = builder.AddTemplate("SELECT /**select**/ FROM Users");
|
||||
var all = builder.AddTemplate("SELECT Name, /**select**/, Age FROM Users");
|
||||
|
||||
builder.Select("Id");
|
||||
|
||||
var ids = connection.Query<int>(justId.RawSql, justId.Parameters);
|
||||
var users = connection.Query<User>(all.RawSql, all.Parameters);
|
||||
|
||||
foreach (var u in data)
|
||||
{
|
||||
if (!ids.Any(i => u.Id == i)) throw new Exception("Missing ids in select");
|
||||
if (!users.Any(a => a.Id == u.Id && a.Name == u.Name && a.Age == u.Age)) throw new Exception("Missing users in select");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BuilderTemplateWOComposition()
|
||||
{
|
||||
var builder = new SqlBuilder();
|
||||
var template = builder.AddTemplate("SELECT COUNT(*) FROM Users WHERE Age = @age", new {age = 5});
|
||||
|
||||
if (template.RawSql == null) throw new Exception("RawSql null");
|
||||
if (template.Parameters == null) throw new Exception("Parameters null");
|
||||
|
||||
using (var connection = GetOpenConnection())
|
||||
{
|
||||
connection.Insert(new User { Age = 5, Name = "Testy McTestington" });
|
||||
|
||||
if (connection.Query<int>(template.RawSql, template.Parameters).Single() != 1)
|
||||
throw new Exception("Query failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,11 @@ namespace Dapper.Contrib.Extensions
|
||||
|
||||
private static IEnumerable<PropertyInfo> KeyPropertiesCache(Type type)
|
||||
{
|
||||
if (KeyProperties.ContainsKey(type.TypeHandle))
|
||||
|
||||
IEnumerable<PropertyInfo> pi;
|
||||
if (KeyProperties.TryGetValue(type.TypeHandle,out pi))
|
||||
{
|
||||
return KeyProperties[type.TypeHandle];
|
||||
return pi;
|
||||
}
|
||||
|
||||
var allProperties = TypePropertiesCache(type);
|
||||
@@ -51,9 +53,10 @@ namespace Dapper.Contrib.Extensions
|
||||
}
|
||||
private static IEnumerable<PropertyInfo> TypePropertiesCache(Type type)
|
||||
{
|
||||
if (TypeProperties.ContainsKey(type.TypeHandle))
|
||||
IEnumerable<PropertyInfo> pis;
|
||||
if (TypeProperties.TryGetValue(type.TypeHandle, out pis))
|
||||
{
|
||||
return TypeProperties[type.TypeHandle];
|
||||
return pis;
|
||||
}
|
||||
|
||||
var properties = type.GetProperties().Where(IsWriteable);
|
||||
@@ -325,9 +328,10 @@ namespace Dapper.Contrib.Extensions
|
||||
{
|
||||
Type typeOfT = typeof(T);
|
||||
|
||||
if (TypeCache.ContainsKey(typeOfT))
|
||||
object k;
|
||||
if (TypeCache.TryGetValue(typeOfT, out k))
|
||||
{
|
||||
return (T)TypeCache[typeOfT];
|
||||
return (T)k;
|
||||
}
|
||||
var assemblyBuilder = GetAsmBuilder(typeOfT.Name);
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<?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>
|
||||
<ItemGroup>
|
||||
<None Include="Dapper.Rainbow.nuspec" />
|
||||
</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>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>Dapper.Rainbow</id>
|
||||
<version>0.1.1</version>
|
||||
<title>Dapper.Rainbow</title>
|
||||
<authors>Sam Saffron</authors>
|
||||
<owners>Sam Saffron</owners>
|
||||
<licenseUrl>http://www.apache.org/licenses/LICENSE-2.0</licenseUrl>
|
||||
<projectUrl>http://code.google.com/p/dapper-dot-net/</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>
|
||||
Trivial micro-orm implemented on Dapper, provides with CRUD helpers.
|
||||
</description>
|
||||
<summary>
|
||||
A demo is available at https://gist.github.com/1599013 .
|
||||
The implementation was extracted from http://data.stackexchange.com source at: http://code.google.com/p/stack-exchange-data-explorer/ .
|
||||
Data explorer uses "Rainbow" exclusively for all database access.
|
||||
</summary>
|
||||
<releaseNotes>* version 0.1 </releaseNotes>
|
||||
<copyright>Copyright Sam Saffron 2012</copyright>
|
||||
<tags>orm dapper micro-orm</tags>
|
||||
<dependencies>
|
||||
<dependency id="Dapper" version="1.8" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="bin\Release\Dapper.Rainbow.dll" target="lib\net40" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
License: http://www.apache.org/licenses/LICENSE-2.0
|
||||
Home page: http://code.google.com/p/dapper-dot-net/
|
||||
*/
|
||||
|
||||
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((object)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 Init(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;
|
||||
}
|
||||
|
||||
protected 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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("I sample mini ORM implementation using Dapper")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Dapper.Rainbow")]
|
||||
[assembly: AssemblyCopyright("Sam Saffron 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("0.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("0.1.0.0")]
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
License: http://www.apache.org/licenses/LICENSE-2.0
|
||||
Home page: http://code.google.com/p/dapper-dot-net/
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,36 @@
|
||||
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")]
|
||||
@@ -0,0 +1,158 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -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
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<DocumentationFile>bin\Debug\Dapper.XML</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -36,7 +38,6 @@
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SqlMapper.cs" />
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// 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")]
|
||||
|
||||
+662
-270
File diff suppressed because it is too large
Load Diff
+15
-6
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata schemaVersion="2">
|
||||
<id>Dapper</id>
|
||||
<version>1.6</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>
|
||||
@@ -183,7 +183,7 @@
|
||||
<LastGenOutput>DataClasses.designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Linq;
|
||||
using System.Data.SqlClient;
|
||||
using System.Diagnostics;
|
||||
@@ -9,6 +10,8 @@ using Dapper;
|
||||
using Massive;
|
||||
using NHibernate.Criterion;
|
||||
using NHibernate.Linq;
|
||||
using ServiceStack.OrmLite;
|
||||
using ServiceStack.OrmLite.SqlServer;
|
||||
using SqlMapper.Linq2Sql;
|
||||
using SqlMapper.NHibernate;
|
||||
using Dapper.Contrib.Extensions;
|
||||
@@ -191,6 +194,11 @@ namespace SqlMapper
|
||||
// Soma
|
||||
var somadb = new Soma.Core.Db(new SomaConfig());
|
||||
tests.Add(id => somadb.Find<Post>(id), "Soma");
|
||||
|
||||
//ServiceStack's OrmLite:
|
||||
OrmLiteConfig.DialectProvider = SqlServerOrmLiteDialectProvider.Instance; //Using SQL Server
|
||||
IDbCommand ormLiteCmd = Program.GetOpenConnection().CreateCommand();
|
||||
tests.Add(id => ormLiteCmd.QueryById<Post>(id), "OrmLite QueryById");
|
||||
|
||||
// HAND CODED
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Reflection;
|
||||
|
||||
namespace SqlMapper
|
||||
{
|
||||
[ServiceStack.DataAnnotations.Alias("Posts")]
|
||||
[Soma.Core.Table(Name = "Posts")]
|
||||
class Post
|
||||
{
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is automatically generated by Visual Studio .Net. It is
|
||||
used to store generic object data source configuration information.
|
||||
Renaming the file extension or editing the content of this file may
|
||||
cause the file to be unrecognizable by the program.
|
||||
-->
|
||||
<GenericObjectDataSource DisplayName="tempdbEntities1" Identifier="SqlMapper.EntityFramework.tempdbEntities1" ProviderType="Microsoft.VisualStudio.DataDesign.DataSourceProviders.EntityDataModel.EdmDataSourceProvider" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
|
||||
<TypeInfo>SqlMapper.EntityFramework.tempdbEntities1, EntityFramework.Model.Designer.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
|
||||
</GenericObjectDataSource>
|
||||
+300
-16
@@ -7,16 +7,93 @@ using System.Data.SqlServerCe;
|
||||
using System.IO;
|
||||
using System.Data;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
namespace SqlMapper
|
||||
{
|
||||
|
||||
|
||||
class Tests
|
||||
{
|
||||
|
||||
SqlConnection connection = Program.GetOpenConnection();
|
||||
|
||||
public class AbstractInheritance
|
||||
{
|
||||
public abstract class Order
|
||||
{
|
||||
internal int Internal { get; set; }
|
||||
protected int Protected { get; set; }
|
||||
public int Public { get; set; }
|
||||
|
||||
public int ProtectedVal { get { return Protected; } }
|
||||
}
|
||||
|
||||
public class ConcreteOrder : Order
|
||||
{
|
||||
public int Concrete { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/q/8593871
|
||||
public void TestAbstractInheritance()
|
||||
{
|
||||
var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First();
|
||||
|
||||
order.Internal.IsEqualTo(1);
|
||||
order.ProtectedVal.IsEqualTo(2);
|
||||
order.Public.IsEqualTo(3);
|
||||
order.Concrete.IsEqualTo(4);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void TestListOfAnsiStrings()
|
||||
{
|
||||
var results = connection.Query<string>("select * from (select 'a' str union select 'b' union select 'c') X where str in @strings",
|
||||
new { strings = new[] { new DbString { IsAnsi = true, Value = "a" }, new DbString { IsAnsi = true, Value = "b" } } }).ToList();
|
||||
|
||||
results[0].IsEqualTo("a");
|
||||
results[1].IsEqualTo("b");
|
||||
}
|
||||
|
||||
public void TestNullableGuidSupport()
|
||||
{
|
||||
var guid = connection.Query<Guid?>("select null").First();
|
||||
guid.IsNull();
|
||||
|
||||
guid = Guid.NewGuid();
|
||||
var guid2 = connection.Query<Guid?>("select @guid", new { guid }).First();
|
||||
guid.IsEqualTo(guid2);
|
||||
}
|
||||
|
||||
public void TestNonNullableGuidSupport()
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
var guid2 = connection.Query<Guid?>("select @guid", new { guid }).First();
|
||||
Assert.IsTrue(guid == guid2);
|
||||
}
|
||||
|
||||
struct Car
|
||||
{
|
||||
public enum TrapEnum : int
|
||||
{
|
||||
A = 1,
|
||||
B = 2
|
||||
}
|
||||
public string Name;
|
||||
public int Age { get; set; }
|
||||
public TrapEnum Trap { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public void TestStructs()
|
||||
{
|
||||
var car = connection.Query<Car>("select 'Ford' Name, 21 Age, 2 Trap").First();
|
||||
|
||||
car.Age.IsEqualTo(21);
|
||||
car.Name.IsEqualTo("Ford");
|
||||
((int)car.Trap).IsEqualTo(2);
|
||||
}
|
||||
|
||||
public void SelectListInt()
|
||||
{
|
||||
connection.Query<int>("select 1 union all select 2 union all select 3")
|
||||
@@ -24,7 +101,7 @@ namespace SqlMapper
|
||||
}
|
||||
public void SelectBinary()
|
||||
{
|
||||
connection.Query<byte[]>("select cast(1 as varbinary(4))").First().SequenceEqual(new byte[] {1});
|
||||
connection.Query<byte[]>("select cast(1 as varbinary(4))").First().SequenceEqual(new byte[] { 1 });
|
||||
}
|
||||
public void PassInIntArray()
|
||||
{
|
||||
@@ -38,6 +115,40 @@ namespace SqlMapper
|
||||
.IsSequenceEqualTo(new int[0]);
|
||||
}
|
||||
|
||||
public void TestSchemaChanged()
|
||||
{
|
||||
connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
|
||||
var d = connection.Query<Dog>("select * from #dog").Single();
|
||||
d.Name.IsEqualTo("Alf");
|
||||
d.Age.IsEqualTo(1);
|
||||
connection.Execute("alter table #dog drop column Name");
|
||||
d = connection.Query<Dog>("select * from #dog").Single();
|
||||
d.Name.IsNull();
|
||||
d.Age.IsEqualTo(1);
|
||||
connection.Execute("drop table #dog");
|
||||
}
|
||||
|
||||
public void TestSchemaChangedMultiMap()
|
||||
{
|
||||
connection.Execute("create table #dog(Age int, Name nvarchar(max)) insert #dog values(1, 'Alf')");
|
||||
var tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single();
|
||||
|
||||
tuple.Item1.Name.IsEqualTo("Alf");
|
||||
tuple.Item1.Age.IsEqualTo(1);
|
||||
tuple.Item2.Name.IsEqualTo("Alf");
|
||||
tuple.Item2.Age.IsEqualTo(1);
|
||||
|
||||
connection.Execute("alter table #dog drop column Name");
|
||||
tuple = connection.Query<Dog, Dog, Tuple<Dog, Dog>>("select * from #dog d1 join #dog d2 on 1=1", (d1, d2) => Tuple.Create(d1, d2), splitOn: "Age").Single();
|
||||
|
||||
tuple.Item1.Name.IsNull();
|
||||
tuple.Item1.Age.IsEqualTo(1);
|
||||
tuple.Item2.Name.IsNull();
|
||||
tuple.Item2.Age.IsEqualTo(1);
|
||||
|
||||
connection.Execute("drop table #dog");
|
||||
}
|
||||
|
||||
public void TestReadMultipleIntegersWithSplitOnAny()
|
||||
{
|
||||
connection.Query<int, int, int, Tuple<int, int, int>>(
|
||||
@@ -185,7 +296,7 @@ namespace SqlMapper
|
||||
|
||||
class Student
|
||||
{
|
||||
public string Name {get; set;}
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
}
|
||||
|
||||
@@ -224,7 +335,7 @@ namespace SqlMapper
|
||||
internal int Internal { set { _internal = value; } }
|
||||
|
||||
public int _priv;
|
||||
internal int Priv { set { _priv = value; } }
|
||||
private int Priv { set { _priv = value; } }
|
||||
}
|
||||
|
||||
public void TestSetInternal()
|
||||
@@ -287,6 +398,26 @@ namespace SqlMapper
|
||||
gotException.IsTrue();
|
||||
}
|
||||
|
||||
public void TestNakedBigInt()
|
||||
{
|
||||
long foo = 12345;
|
||||
var result = connection.Query<long>("select @foo", new { foo }).Single();
|
||||
foo.IsEqualTo(result);
|
||||
}
|
||||
|
||||
public void TestBigIntMember()
|
||||
{
|
||||
long foo = 12345;
|
||||
var result = connection.Query<WithBigInt>(@"
|
||||
declare @bar table(Value bigint)
|
||||
insert @bar values (@foo)
|
||||
select * from @bar", new { foo }).Single();
|
||||
result.Value.IsEqualTo(foo);
|
||||
}
|
||||
class WithBigInt
|
||||
{
|
||||
public long Value { get; set; }
|
||||
}
|
||||
|
||||
class User
|
||||
{
|
||||
@@ -374,7 +505,7 @@ Order by p.Id
|
||||
|
||||
data[2].Owner.IsNull();
|
||||
}
|
||||
|
||||
|
||||
connection.Execute("drop table #Users drop table #Posts");
|
||||
|
||||
}
|
||||
@@ -757,7 +888,7 @@ end");
|
||||
this.numbers = numbers;
|
||||
}
|
||||
|
||||
public void AddParameters(IDbCommand command)
|
||||
public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity)
|
||||
{
|
||||
var sqlCommand = (SqlCommand)command;
|
||||
sqlCommand.CommandType = CommandType.StoredProcedure;
|
||||
@@ -862,10 +993,12 @@ end");
|
||||
public void TestUnexpectedDataMessage()
|
||||
{
|
||||
string msg = null;
|
||||
try {
|
||||
try
|
||||
{
|
||||
connection.Query<int>("select count(1) where 1 = @Foo", new WithBizarreData { Foo = new GenericUriParser(GenericUriParserOptions.Default), Bar = 23 }).First();
|
||||
|
||||
} catch(Exception ex)
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
msg = ex.Message;
|
||||
}
|
||||
@@ -923,7 +1056,7 @@ end");
|
||||
connection.Query<User, User, User>("select 1 A, 2 B, 3 C", (x, y) => x);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
{
|
||||
// expecting an app exception due to multi mapping being bodged
|
||||
}
|
||||
|
||||
@@ -989,19 +1122,19 @@ Order by p.Id";
|
||||
var p = new DynamicParameters();
|
||||
|
||||
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
|
||||
connection.Execute("select @b = null",p);
|
||||
connection.Execute("select @b = null", p);
|
||||
|
||||
p.Get<int?>("@b").IsNull();
|
||||
}
|
||||
class Foo1
|
||||
{
|
||||
class Foo1
|
||||
{
|
||||
public int Id;
|
||||
public int BarId { get; set; }
|
||||
}
|
||||
}
|
||||
class Bar1
|
||||
{
|
||||
public int BarId;
|
||||
public string Name { get; set; }
|
||||
public int BarId;
|
||||
public string Name { get; set; }
|
||||
}
|
||||
public void TestMultiMapperIsNotConfusedWithUnorderedCols()
|
||||
{
|
||||
@@ -1051,5 +1184,156 @@ Order by p.Id";
|
||||
var output = connection.Query<WithPrivateConstructor>("select 1 as Foo").First();
|
||||
output.Foo.IsEqualTo(1);
|
||||
}
|
||||
|
||||
public void TestAppendingAnonClasses()
|
||||
{
|
||||
DynamicParameters p = new DynamicParameters();
|
||||
p.AddDynamicParams(new { A = 1, B = 2 });
|
||||
p.AddDynamicParams(new { C = 3, D = 4 });
|
||||
|
||||
var result = connection.Query("select @A a,@B b,@C c,@D d", p).Single();
|
||||
|
||||
((int)result.a).IsEqualTo(1);
|
||||
((int)result.b).IsEqualTo(2);
|
||||
((int)result.c).IsEqualTo(3);
|
||||
((int)result.d).IsEqualTo(4);
|
||||
}
|
||||
|
||||
public void TestAppendingAList()
|
||||
{
|
||||
DynamicParameters p = new DynamicParameters();
|
||||
var list = new int[] { 1, 2, 3 };
|
||||
p.AddDynamicParams(new { list });
|
||||
|
||||
var result = connection.Query<int>("select * from (select 1 A union all select 2 union all select 3) X where A in @list", p).ToList();
|
||||
|
||||
result[0].IsEqualTo(1);
|
||||
result[1].IsEqualTo(2);
|
||||
result[2].IsEqualTo(3);
|
||||
}
|
||||
|
||||
public void TestUniqueIdentifier()
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
var result = connection.Query<Guid>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
|
||||
result.IsEqualTo(guid);
|
||||
}
|
||||
public void TestNullableUniqueIdentifierNonNull()
|
||||
{
|
||||
Guid? guid = Guid.NewGuid();
|
||||
var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
|
||||
result.IsEqualTo(guid);
|
||||
}
|
||||
public void TestNullableUniqueIdentifierNull()
|
||||
{
|
||||
Guid? guid = null;
|
||||
var result = connection.Query<Guid?>("declare @foo uniqueidentifier set @foo = @guid select @foo", new { guid }).Single();
|
||||
result.IsEqualTo(guid);
|
||||
}
|
||||
|
||||
|
||||
public void TestFailInASaneWayWithWrongStructColumnTypes()
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.Query<CanHazInt>("select cast(1 as bigint) Value").Single();
|
||||
throw new Exception("Should not have got here");
|
||||
} catch(DataException ex)
|
||||
{
|
||||
ex.Message.IsEqualTo("Error parsing column 0 (Value=1 - Int64)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void TestProcWithOutParameter()
|
||||
{
|
||||
connection.Execute(
|
||||
@"CREATE PROCEDURE #TestProcWithOutParameter
|
||||
@ID int output,
|
||||
@Foo varchar(100),
|
||||
@Bar int
|
||||
AS
|
||||
SET @ID = @Bar + LEN(@Foo)");
|
||||
var obj = new
|
||||
{
|
||||
ID = 0,
|
||||
Foo = "abc",
|
||||
Bar = 4
|
||||
};
|
||||
var args = new DynamicParameters(obj);
|
||||
args.Add("ID", 0, direction: ParameterDirection.Output);
|
||||
connection.Execute("#TestProcWithOutParameter", args, commandType: CommandType.StoredProcedure);
|
||||
args.Get<int>("ID").IsEqualTo(7);
|
||||
}
|
||||
public void TestProcWithOutAndReturnParameter()
|
||||
{
|
||||
connection.Execute(
|
||||
@"CREATE PROCEDURE #TestProcWithOutAndReturnParameter
|
||||
@ID int output,
|
||||
@Foo varchar(100),
|
||||
@Bar int
|
||||
AS
|
||||
SET @ID = @Bar + LEN(@Foo)
|
||||
RETURN 42");
|
||||
var obj = new
|
||||
{
|
||||
ID = 0,
|
||||
Foo = "abc",
|
||||
Bar = 4
|
||||
};
|
||||
var args = new DynamicParameters(obj);
|
||||
args.Add("ID", 0, direction: ParameterDirection.Output);
|
||||
args.Add("result", 0, direction: ParameterDirection.ReturnValue);
|
||||
connection.Execute("#TestProcWithOutAndReturnParameter", args, commandType: CommandType.StoredProcedure);
|
||||
args.Get<int>("ID").IsEqualTo(7);
|
||||
args.Get<int>("result").IsEqualTo(42);
|
||||
}
|
||||
struct CanHazInt
|
||||
{
|
||||
public int Value { get; set; }
|
||||
}
|
||||
public void TestInt16Usage()
|
||||
{
|
||||
connection.Query<short>("select cast(42 as smallint)").Single().IsEqualTo((short)42);
|
||||
connection.Query<short?>("select cast(42 as smallint)").Single().IsEqualTo((short?)42);
|
||||
connection.Query<short?>("select cast(null as smallint)").Single().IsEqualTo((short?)null);
|
||||
|
||||
// hmmm.... these don't work currently... adding TODO
|
||||
//connection.Query<ShortEnum>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum)42);
|
||||
//connection.Query<ShortEnum?>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum?)42);
|
||||
//connection.Query<ShortEnum?>("select cast(null as smallint)").Single().IsEqualTo((ShortEnum?)null);
|
||||
|
||||
var row =
|
||||
connection.Query<WithInt16Values>(
|
||||
"select cast(1 as smallint) as NonNullableInt16, cast(2 as smallint) as NullableInt16, cast(3 as smallint) as NonNullableInt16Enum, cast(4 as smallint) as NullableInt16Enum")
|
||||
.Single();
|
||||
row.NonNullableInt16.IsEqualTo((short)1);
|
||||
row.NullableInt16.IsEqualTo((short)2);
|
||||
row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Three);
|
||||
row.NullableInt16Enum.IsEqualTo(ShortEnum.Four);
|
||||
|
||||
row =
|
||||
connection.Query<WithInt16Values>(
|
||||
"select cast(5 as smallint) as NonNullableInt16, cast(null as smallint) as NullableInt16, cast(6 as smallint) as NonNullableInt16Enum, cast(null as smallint) as NullableInt16Enum")
|
||||
.Single();
|
||||
row.NonNullableInt16.IsEqualTo((short)5);
|
||||
row.NullableInt16.IsEqualTo((short?)null);
|
||||
row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Six);
|
||||
row.NullableInt16Enum.IsEqualTo((ShortEnum?)null);
|
||||
}
|
||||
|
||||
|
||||
public class WithInt16Values
|
||||
{
|
||||
public short NonNullableInt16 { get; set; }
|
||||
public short? NullableInt16 { get; set; }
|
||||
public ShortEnum NonNullableInt16Enum { get; set; }
|
||||
public ShortEnum? NullableInt16Enum { get; set; }
|
||||
|
||||
}
|
||||
public enum ShortEnum : short
|
||||
{
|
||||
Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user