提交 ce152da4 编写于 作者: N Nick Craver

Merge branch 'pr/352'

......@@ -63,7 +63,7 @@ public static partial class SqlMapperExtensions
foreach (var property in TypePropertiesCache(type))
{
var val = res[property.Name];
property.SetValue(obj, val, null);
property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null);
}
((IProxy)obj).IsDirty = false; //reset change tracking and return
......@@ -114,7 +114,7 @@ public static partial class SqlMapperExtensions
foreach (var property in TypePropertiesCache(type))
{
var val = res[property.Name];
property.SetValue(obj, val, null);
property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null);
}
((IProxy)obj).IsDirty = false; //reset change tracking and return
list.Add(obj);
......@@ -200,8 +200,9 @@ public static partial class SqlMapperExtensions
type = type.GetGenericArguments()[0];
var keyProperties = KeyPropertiesCache(type);
if (!keyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] property");
var explicitKeyProperties = ExplicitKeyPropertiesCache(type);
if (!keyProperties.Any() && !explicitKeyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
var name = GetTableName(type);
......@@ -209,6 +210,7 @@ public static partial class SqlMapperExtensions
sb.AppendFormat("update {0} set ", name);
var allProperties = TypePropertiesCache(type);
keyProperties.AddRange(explicitKeyProperties);
var computedProperties = ComputedPropertiesCache(type);
var nonIdProps = allProperties.Except(keyProperties.Union(computedProperties)).ToList();
......@@ -249,10 +251,12 @@ public static partial class SqlMapperExtensions
type = type.GetGenericArguments()[0];
var keyProperties = KeyPropertiesCache(type);
if (!keyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] property");
var explicitKeyProperties = ExplicitKeyPropertiesCache(type);
if (!keyProperties.Any() && !explicitKeyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
var name = GetTableName(type);
keyProperties.AddRange(explicitKeyProperties);
var sb = new StringBuilder();
sb.AppendFormat("delete from {0} where ", name);
......@@ -294,30 +298,20 @@ public partial class SqlServerAdapter
{
public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = String.Format("insert into {0} ({1}) values ({2});select SCOPE_IDENTITY() id", tableName, columnList, parameterList);
var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout);
var id = (int)multi.Read().First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!propertyInfos.Any()) return id;
var first = multi.Read().FirstOrDefault();
if (first == null || first.id == null) return 0;
var idProperty = propertyInfos.First();
if (idProperty.PropertyType.Name == "Int16") //for short id/key types issue #196
idProperty.SetValue(entityToInsert, (Int16)id, null);
else
idProperty.SetValue(entityToInsert, id, null);
return id;
var id = (int)first.id;
var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!pi.Any()) return id;
var idp = pi.First();
idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
//var cmd = String.Format("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
//await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
//var r = await connection.QueryAsync<dynamic>("select SCOPE_IDENTITY() id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
//var id = (int)r.First().id;
//var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
//if (propertyInfos.Any())
// propertyInfos.First().SetValue(entityToInsert, id, null);
//return id;
return id;
}
}
......@@ -326,14 +320,39 @@ public partial class SqlCeServerAdapter
public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = String.Format("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
var r = (await connection.QueryAsync<dynamic>("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false)).ToList();
var r = await connection.QueryAsync<dynamic>("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
if (r.First() == null || r.First().id == null) return 0;
var id = (int)r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any())
propertyInfos.First().SetValue(entityToInsert, id, null);
var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!pi.Any()) return id;
var idp = pi.First();
idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
return id;
}
}
public partial class MySqlAdapter : ISqlAdapter
{
public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName,
string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = String.Format("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
var r = await connection.QueryAsync<dynamic>("select LAST_INSERT_ID()", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
var id = r.First().id;
if (id == null) return 0;
var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!pi.Any()) return id;
var idp = pi.First();
idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
return id;
}
}
......@@ -383,15 +402,16 @@ public partial class SQLiteAdapter
public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = String.Format("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
var cmd = String.Format("insert into {0} ({1}) values ({2}); select last_insert_rowid() id", tableName, columnList, parameterList);
var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout);
await connection.ExecuteAsync(cmd, entityToInsert, transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
var id = (int)multi.Read().First().id;
var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!pi.Any()) return id;
var idp = pi.First();
idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
var r = await connection.QueryAsync<dynamic>("select last_insert_rowid() id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
var id = (int)r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any())
propertyInfos.First().SetValue(entityToInsert, id, null);
return id;
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E5482A3B-2C2A-4907-9804-C191F18FA622}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dapper.Contrib.Tests</RootNamespace>
<AssemblyName>Dapper.Contrib.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;MSSQL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<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.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL" />
<Reference Include="System.Transactions" />
<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="..\Dapper.Contrib.Tests NET45\TestsAsync.cs">
<Link>TestsAsync.cs</Link>
</Compile>
<Compile Include="..\Dapper.Contrib.Tests\Assert.cs">
<Link>Assert.cs</Link>
</Compile>
<Compile Include="..\Dapper.Contrib.Tests\Tests.cs">
<Link>Tests.cs</Link>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Dapper NET45\Dapper NET45.csproj">
<Project>{0fff5bc7-0a4b-4d87-835e-4fad70937507}</Project>
<Name>Dapper NET45</Name>
</ProjectReference>
<ProjectReference Include="..\Dapper.Contrib NET45\Dapper.Contrib NET45.csproj">
<Project>{302ec82f-a81b-48c5-b653-b5c75d2bd103}</Project>
<Name>Dapper.Contrib NET45</Name>
</ProjectReference>
<ProjectReference Include="..\Dapper.SqlBuilder\Dapper.SqlBuilder.csproj">
<Project>{bf782ef1-2b0f-42fa-9dd0-928454a94c6d}</Project>
<Name>Dapper.SqlBuilder</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.Data.SqlClient;
using System.Data.SqlServerCe;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Dapper.Contrib.Tests
{
class Program
{
static void Main(string[] args)
{
SetupMsSqlDatabase();
SetupTables();
RunTests();
DropTables();
SetupTables();
RunAsyncTests();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
private static void SetupMsSqlDatabase()
{
using (var connection = new SqlConnection("Data Source = .\\SQLEXPRESS;Initial Catalog=master;Integrated Security=SSPI"))
{
connection.Open();
var exists = connection.Query<int>("SELECT count(*) FROM master.sys.databases WHERE name = @name",
new { name = "DapperContribMsSqlTests" }).First();
if (exists > 0)
{
connection.Execute("drop database DapperContribMsSqlTests");
}
connection.Execute("create database DapperContribMsSqlTests");
}
}
private static void DropTables()
{
using (var connection = new SqlConnection("Data Source = .\\SQLEXPRESS;Initial Catalog=DapperContribMsSqlTests;Integrated Security=SSPI"))
{
connection.Open();
connection.Execute("alter database DapperContribMsSqlTests set single_user with rollback immediate");
connection.Execute(@" drop table Stuff");
connection.Execute(@" drop table People ");
connection.Execute(@" drop table Users");
connection.Execute(@" drop table Automobiles ");
connection.Execute(@" drop table Results ");
connection.Execute(@" drop table ObjectX ");
connection.Execute(@" drop table ObjectY ");
}
Console.WriteLine("Created database");
}
private static void SetupTables()
{
using (var connection = new SqlConnection("Data Source = .\\SQLEXPRESS;Initial Catalog=DapperContribMsSqlTests;Integrated Security=SSPI"))
{
connection.Open();
connection.Execute(@" create table Stuff (TheId int IDENTITY(1,1) not null, Name nvarchar(100) not null, Created DateTime null) ");
connection.Execute(@" create table People (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null) ");
connection.Execute(@" create table Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table Results (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, [Order] int not null) ");
connection.Execute(@" create table ObjectX (ObjectXId nvarchar(100) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table ObjectY (ObjectYId int not null, Name nvarchar(100) not null) ");
}
Console.WriteLine("Created database");
}
private static void RunTests()
{
var tester = new Tests();
foreach (var method in typeof(Tests).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
Console.Write("Running " + method.Name);
method.Invoke(tester, null);
Console.WriteLine(" - OK!");
}
}
private static void RunAsyncTests()
{
var tester = new TestsAsync();
foreach (var method in typeof(TestsAsync).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
Console.Write("Running " + method.Name);
Task.WaitAll((Task)method.Invoke(tester, null));
Console.WriteLine(" - OK!");
}
}
}
}
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.Contrib.Tests NET45")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Dapper.Contrib.Tests NET45")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[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("2d6cdd3d-b94b-4cd4-842a-60c6e4c93c5c")]
// 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;
namespace Dapper.Contrib.Tests
{
/// <summary>
/// Assert extensions borrowed from Sam's code in DapperTests
/// </summary>
static class Assert
{
public static void IsEqualTo<T>(this T obj, T other)
{
if (!obj.Equals(other))
{
throw new ApplicationException(string.Format("{0} should be equals to {1}", obj, other));
}
}
public static void IsMoreThan(this int obj, int other)
{
if (obj < other)
{
throw new ApplicationException(string.Format("{0} should be larger than {1}", obj, other));
}
}
public static void IsMoreThan(this long obj, int other)
{
if (obj < other)
{
throw new ApplicationException(string.Format("{0} should be larger than {1}", obj, other));
}
}
public static void IsSequenceEqualTo<T>(this IEnumerable<T> obj, IEnumerable<T> other)
{
if (!obj.SequenceEqual(other))
{
throw new ApplicationException(string.Format("{0} should be equals to {1}", obj, other));
}
}
public static void IsFalse(this bool b)
{
if (b)
{
throw new ApplicationException("Expected false");
}
}
public static void IsTrue(this bool b)
{
if (!b)
{
throw new ApplicationException("Expected true");
}
}
public static void IsNull(this object obj)
{
if (obj != null)
{
throw new ApplicationException("Expected null");
}
}
public static void IsNotNull(this object obj)
{
if (obj == null)
{
throw new ApplicationException("Expected not null");
}
}
}
}
\ No newline at end of file
<?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)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Dapper.Contrib.Tests</RootNamespace>
<AssemblyName>Dapper.Contrib.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;SQLITE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.98.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL" />
<Reference Include="System.Transactions" />
<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="..\Dapper.Contrib.Tests NET45\TestsAsync.cs">
<Link>TestsAsync.cs</Link>
</Compile>
<Compile Include="..\Dapper.Contrib.Tests\Tests.cs">
<Link>Tests.cs</Link>
</Compile>
<Compile Include="Assert.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Dapper NET45\Dapper NET45.csproj">
<Project>{0fff5bc7-0a4b-4d87-835e-4fad70937507}</Project>
<Name>Dapper NET45</Name>
</ProjectReference>
<ProjectReference Include="..\Dapper.Contrib NET45\Dapper.Contrib NET45.csproj">
<Project>{302ec82f-a81b-48c5-b653-b5c75d2bd103}</Project>
<Name>Dapper.Contrib NET45</Name>
</ProjectReference>
<ProjectReference Include="..\Dapper.SqlBuilder\Dapper.SqlBuilder.csproj">
<Project>{BF782EF1-2B0F-42FA-9DD0-928454A94C6D}</Project>
<Name>Dapper.SqlBuilder</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="System.Data.SQLite.dll" />
<Content Include="x64\SQLite.Interop.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="x86\SQLite.Interop.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</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.Data.SQLite;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
namespace Dapper.Contrib.Tests
{
class Program
{
static void Main(string[] args)
{
Setup();
RunTests();
Setup();
RunAsyncTests();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
private static void Setup()
{
var projLoc = Assembly.GetAssembly(typeof(Program)).Location;
var projFolder = Path.GetDirectoryName(projLoc);
if (File.Exists(projFolder + "\\Test.sqlite"))
File.Delete(projFolder + "\\Test.sqlite");
SQLiteConnection.CreateFile(projFolder + "\\Test.sqlite");
var connectionString = "Data Source = " + projFolder + "\\Test.sqlite;";
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
connection.Execute(@" create table Stuff (TheId integer primary key autoincrement not null, Name nvarchar(100) not null, Created DateTime null) ");
connection.Execute(@" create table People (Id integer primary key autoincrement not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table Users (Id integer primary key autoincrement not null, Name nvarchar(100) not null, Age int not null) ");
connection.Execute(@" create table Automobiles (Id integer primary key autoincrement not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table Results (Id integer primary key autoincrement not null, Name nvarchar(100) not null, [Order] int not null) ");
connection.Execute(@" create table ObjectX (ObjectXId nvarchar(100) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table ObjectY (ObjectYId integer not null, Name nvarchar(100) not null) ");
}
Console.WriteLine("Created database");
}
private static void RunTests()
{
var tester = new Tests();
foreach (var method in typeof(Tests).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
Console.Write("Running " + method.Name);
method.Invoke(tester, null);
Console.WriteLine(" - OK!");
}
}
private static void RunAsyncTests()
{
var tester = new TestsAsync();
foreach (var method in typeof(TestsAsync).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
Console.Write("Running " + method.Name);
Task.WaitAll((Task)method.Invoke(tester, null));
Console.WriteLine(" - OK!");
}
}
}
}
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.Contrib.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Dapper.Contrib.Tests")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
[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("9d5920b6-d6af-41ca-b851-803ac922d933")]
// 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.40.0.0")]
[assembly: AssemblyFileVersion("1.40.0.0")]
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
......@@ -36,6 +36,8 @@ private static void Setup()
connection.Execute(@" create table Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null) ");
connection.Execute(@" create table Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table Results (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, [Order] int not null) ");
connection.Execute(@" create table ObjectX (ObjectXId nvarchar(100) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table ObjectY (ObjectYId int not null, Name nvarchar(100) not null) ");
}
Console.WriteLine("Created database");
}
......
using System;
using System.Collections.Generic;
using System.Data;
#if SQLITE
using System.Data.SQLite;
#elif MSSQL
using System.Data.SqlClient;
#endif
using System.Data.SqlServerCe;
using System.IO;
using System.Linq;
......@@ -18,10 +23,55 @@ private IDbConnection GetOpenConnection()
var projLoc = Assembly.GetAssembly(GetType()).Location;
var projFolder = Path.GetDirectoryName(projLoc);
#if SQLITE
var connection = new SQLiteConnection("Data Source = " + projFolder + "\\Test.sqlite;");
#elif MSSQL
var connection = new SqlConnection("Data Source = .\\SQLEXPRESS;Initial Catalog=DapperContribMsSqlTests;Integrated Security=SSPI");
#else
var connection = new SqlCeConnection("Data Source = " + projFolder + "\\Test.sdf;");
#endif
connection.Open();
return connection;
}
/// <summary>
/// Tests for issue #351
/// </summary>
public async Task InsertGetUpdateDeleteWithExplicitKey()
{
using (var connection = GetOpenConnection())
{
var guid = Guid.NewGuid().ToString();
var o1 = new ObjectX { ObjectXId = guid, Name = "Foo" };
await connection.InsertAsync(o1);
var list1 = (await connection.QueryAsync<ObjectX>("select * from objectx")).ToList();
list1.Count.IsEqualTo(1);
o1 = await connection.GetAsync<ObjectX>(guid);
o1.ObjectXId.IsEqualTo(guid);
o1.Name = "Bar";
await connection.UpdateAsync(o1);
o1 = await connection.GetAsync<ObjectX>(guid);
o1.Name.IsEqualTo("Bar");
await connection.DeleteAsync(o1);
o1 = await connection.GetAsync<ObjectX>(guid);
o1.IsNull();
const int id = 42;
var o2 = new ObjectY() { ObjectYId = id, Name = "Foo" };
await connection.InsertAsync(o2);
var list2 = (await connection.QueryAsync<ObjectY>("select * from objecty")).ToList();
list2.Count.IsEqualTo(1);
o2 = await connection.GetAsync<ObjectY>(id);
o2.ObjectYId.IsEqualTo(id);
o2.Name = "Bar";
await connection.UpdateAsync(o2);
o2 = await connection.GetAsync<ObjectY>(id);
o2.Name.IsEqualTo("Bar");
await connection.DeleteAsync(o2);
o2 = await connection.GetAsync<ObjectY>(id);
o2.IsNull();
}
}
public async Task TableNameAsync()
{
......@@ -87,7 +137,7 @@ public async Task InsertGetUpdateAsync()
(await connection.UpdateAsync(notrackedUser)).IsEqualTo(false); //returns false, user not found
(await connection.InsertAsync(new User { Name = "Adam", Age = 10 }, sqlAdapter: new SqlCeServerAdapter())).IsMoreThan(0);
(await connection.InsertAsync(new User { Name = "Adam", Age = 10 })).IsMoreThan(0);
}
}
......@@ -159,7 +209,7 @@ public async Task BuilderTemplateWOCompositionAsync()
public async Task InsertListAsync()
{
const int numberOfEntities = 100;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......@@ -178,7 +228,7 @@ public async Task InsertListAsync()
public async Task UpdateList()
{
const int numberOfEntities = 100;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......@@ -205,7 +255,7 @@ public async Task UpdateList()
public async Task DeleteList()
{
const int numberOfEntities = 100;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......@@ -230,7 +280,7 @@ public async Task DeleteList()
public async Task GetAllAsync()
{
const int numberOfEntities = 1000;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......
......@@ -33,6 +33,8 @@ private static void Setup()
connection.Execute(@" create table Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null) ");
connection.Execute(@" create table Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table Results (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, [Order] int not null) ");
connection.Execute(@" create table ObjectX (ObjectXId nvarchar(100) not null, Name nvarchar(100) not null) ");
connection.Execute(@" create table ObjectY (ObjectYId int not null, Name nvarchar(100) not null) ");
}
Console.WriteLine("Created database");
}
......
using System;
using System.Collections.Generic;
using System.Data;
#if SQLITE
using System.Data.SQLite;
#elif MSSQL
using System.Data.SqlClient;
#endif
using System.Data.SqlServerCe;
using System.IO;
using System.Linq;
......@@ -11,6 +16,22 @@
namespace Dapper.Contrib.Tests
{
[Table("ObjectX")]
public class ObjectX
{
[ExplicitKey]
public string ObjectXId { get; set; }
public string Name { get; set; }
}
[Table("ObjectY")]
public class ObjectY
{
[ExplicitKey]
public int ObjectYId { get; set; }
public string Name { get; set; }
}
public interface IUser
{
[Key]
......@@ -65,7 +86,13 @@ private IDbConnection GetOpenConnection()
var projLoc = Assembly.GetAssembly(GetType()).Location;
var projFolder = Path.GetDirectoryName(projLoc);
#if SQLITE
var connection = new SQLiteConnection("Data Source = " + projFolder + "\\Test.sqlite;");
#elif MSSQL
var connection = new SqlConnection("Data Source = .\\SQLEXPRESS;Initial Catalog=DapperContribMsSqlTests;Integrated Security=SSPI");
#else
var connection = new SqlCeConnection("Data Source = " + projFolder + "\\Test.sdf;");
#endif
connection.Open();
return connection;
}
......@@ -75,10 +102,57 @@ private IDbConnection GetConnection()
var projLoc = Assembly.GetAssembly(GetType()).Location;
var projFolder = Path.GetDirectoryName(projLoc);
#if SQLITE
var connection = new SQLiteConnection("Data Source = " + projFolder + "\\Test.sqlite;");
#elif MSSQL
var connection = new SqlConnection("Data Source = .\\SQLEXPRESS;Initial Catalog=DapperContribMsSqlTests;Integrated Security=SSPI");
#else
var connection = new SqlCeConnection("Data Source = " + projFolder + "\\Test.sdf;");
#endif
return connection;
}
/// <summary>
/// Tests for issue #351
/// </summary>
public void InsertGetUpdateDeleteWithExplicitKey()
{
using (var connection = GetOpenConnection())
{
var guid = Guid.NewGuid().ToString();
var o1 = new ObjectX { ObjectXId = guid, Name = "Foo" };
connection.Insert(o1);
var list1 = connection.Query<ObjectX>("select * from objectx").ToList();
list1.Count.IsEqualTo(1);
o1 = connection.Get<ObjectX>(guid);
o1.ObjectXId.IsEqualTo(guid);
o1.Name = "Bar";
connection.Update(o1);
o1 = connection.Get<ObjectX>(guid);
o1.Name.IsEqualTo("Bar");
connection.Delete(o1);
o1 = connection.Get<ObjectX>(guid);
o1.IsNull();
const int id = 42;
var o2 = new ObjectY() { ObjectYId = id, Name = "Foo" };
connection.Insert(o2);
var list2 = connection.Query<ObjectY>("select * from objecty").ToList();
list2.Count.IsEqualTo(1);
o2 = connection.Get<ObjectY>(id);
o2.ObjectYId.IsEqualTo(id);
o2.Name = "Bar";
connection.Update(o2);
o2 = connection.Get<ObjectY>(id);
o2.Name.IsEqualTo("Bar");
connection.Delete(o2);
o2 = connection.Get<ObjectY>(id);
o2.IsNull();
}
}
public void ShortIdentity()
{
using (var connection = GetOpenConnection())
......@@ -141,7 +215,7 @@ public void TestClosedConnection()
public void InsertList()
{
const int numberOfEntities = 100;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......@@ -161,7 +235,7 @@ public void InsertList()
public void UpdateList()
{
const int numberOfEntities = 100;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......@@ -188,7 +262,7 @@ public void UpdateList()
public void DeleteList()
{
const int numberOfEntities = 100;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......@@ -247,6 +321,9 @@ public void InsertGetUpdate()
connection.Update(notrackedUser).IsEqualTo(false); //returns false, user not found
}
}
#if SQLITE
#elif MSSQL
#else
public void InsertWithCustomDbType()
{
......@@ -265,6 +342,7 @@ public void InsertWithCustomDbType()
{
sqliteCodeCalled = ex.Message.IndexOf("There was an error parsing the query", StringComparison.InvariantCultureIgnoreCase) >= 0;
}
// ReSharper disable once EmptyGeneralCatchClause
catch (Exception)
{
}
......@@ -276,7 +354,7 @@ public void InsertWithCustomDbType()
throw new Exception("Was expecting sqlite code to be called");
}
}
#endif
public void InsertWithCustomTableNameMapper()
{
......@@ -308,7 +386,7 @@ public void InsertWithCustomTableNameMapper()
public void GetAll()
{
const int numberOfEntities = 100;
const int numberOfEntities = 10;
var users = new List<User>();
for (var i = 0; i < numberOfEntities; i++)
......
......@@ -32,6 +32,7 @@ public interface ITableNameMapper
public delegate string TableNameMapperDelegate(Type type);
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> KeyProperties = new ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>>();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> ExplicitKeyProperties = new ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>>();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> TypeProperties = new ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>>();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> ComputedProperties = new ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>>();
private static readonly ConcurrentDictionary<RuntimeTypeHandle, string> GetQueries = new ConcurrentDictionary<RuntimeTypeHandle, string>();
......@@ -41,10 +42,11 @@ public interface ITableNameMapper
{"sqlconnection", new SqlServerAdapter()},
{"sqlceconnection", new SqlCeServerAdapter()},
{"npgsqlconnection", new PostgresAdapter()},
{"sqliteconnection", new SQLiteAdapter()}
{"sqliteconnection", new SQLiteAdapter()},
{"mysqlconnection", new MySqlAdapter()},
};
private static IEnumerable<PropertyInfo> ComputedPropertiesCache(Type type)
private static List<PropertyInfo> ComputedPropertiesCache(Type type)
{
IEnumerable<PropertyInfo> pi;
if (ComputedProperties.TryGetValue(type.TypeHandle, out pi))
......@@ -58,6 +60,20 @@ private static IEnumerable<PropertyInfo> ComputedPropertiesCache(Type type)
return computedProperties;
}
private static List<PropertyInfo> ExplicitKeyPropertiesCache(Type type)
{
IEnumerable<PropertyInfo> pi;
if (ExplicitKeyProperties.TryGetValue(type.TypeHandle, out pi))
{
return pi.ToList();
}
var explicitKeyProperties = TypePropertiesCache(type).Where(p => p.GetCustomAttributes(true).Any(a => a is ExplicitKeyAttribute)).ToList();
ExplicitKeyProperties[type.TypeHandle] = explicitKeyProperties;
return explicitKeyProperties;
}
private static List<PropertyInfo> KeyPropertiesCache(Type type)
{
......@@ -123,17 +139,18 @@ private static bool IsWriteable(PropertyInfo pi)
if (!GetQueries.TryGetValue(type.TypeHandle, out sql))
{
var keys = KeyPropertiesCache(type);
if (keys.Count() > 1)
throw new DataException("Get<T> only supports an entity with a single [Key] property");
if (!keys.Any())
throw new DataException("Get<T> only supports an entity with a [Key] property");
var explicitKeys = ExplicitKeyPropertiesCache(type);
if (keys.Count() > 1 || explicitKeys.Count() > 1)
throw new DataException("Get<T> only supports an entity with a single [Key] or [ExplicitKey] property");
if (!keys.Any() && !explicitKeys.Any())
throw new DataException("Get<T> only supports an entity with a [Key] or an [ExplicitKey] property");
var onlyKey = keys.First();
var key = keys.Any() ? keys.First() : explicitKeys.First();
var name = GetTableName(type);
// TODO: query information schema and only select fields that are both in information schema and underlying class / interface
sql = "select * from " + name + " where " + onlyKey.Name + " = @id";
sql = "select * from " + name + " where " + key.Name + " = @id";
GetQueries[type.TypeHandle] = sql;
}
......@@ -154,7 +171,7 @@ private static bool IsWriteable(PropertyInfo pi)
foreach (var property in TypePropertiesCache(type))
{
var val = res[property.Name];
property.SetValue(obj, val, null);
property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null);
}
((IProxy)obj).IsDirty = false; //reset change tracking and return
......@@ -207,7 +224,7 @@ private static bool IsWriteable(PropertyInfo pi)
foreach (var property in TypePropertiesCache(type))
{
var val = res[property.Name];
property.SetValue(obj, val, null);
property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null);
}
((IProxy)obj).IsDirty = false; //reset change tracking and return
list.Add(obj);
......@@ -273,10 +290,12 @@ private static string GetTableName(Type type)
var computedProperties = ComputedPropertiesCache(type);
var allPropertiesExceptKeyAndComputed = allProperties.Except(keyProperties.Union(computedProperties)).ToList();
var adapter = GetFormatter(connection);
for (var i = 0; i < allPropertiesExceptKeyAndComputed.Count(); i++)
{
var property = allPropertiesExceptKeyAndComputed.ElementAt(i);
sbColumnList.AppendFormat("[{0}]", property.Name);
adapter.AppendColumnName(sbColumnList, property.Name); //fix for issue #336
if (i < allPropertiesExceptKeyAndComputed.Count() - 1)
sbColumnList.Append(", ");
}
......@@ -296,7 +315,6 @@ private static string GetTableName(Type type)
if (!isList) //single entity
{
var adapter = GetFormatter(connection);
returnVal = adapter.Insert(connection, transaction, commandTimeout, name, sbColumnList.ToString(),
sbParameterList.ToString(), keyProperties, entityToInsert);
}
......@@ -331,8 +349,9 @@ private static string GetTableName(Type type)
type = type.GetGenericArguments()[0];
var keyProperties = KeyPropertiesCache(type);
if (!keyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] property");
var explicitKeyProperties = ExplicitKeyPropertiesCache(type);
if (!keyProperties.Any() && !explicitKeyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
var name = GetTableName(type);
......@@ -340,13 +359,16 @@ private static string GetTableName(Type type)
sb.AppendFormat("update {0} set ", name);
var allProperties = TypePropertiesCache(type);
keyProperties.AddRange(explicitKeyProperties);
var computedProperties = ComputedPropertiesCache(type);
var nonIdProps = allProperties.Except(keyProperties.Union(computedProperties)).ToList();
var adapter = GetFormatter(connection);
for (var i = 0; i < nonIdProps.Count(); i++)
{
var property = nonIdProps.ElementAt(i);
sb.AppendFormat("[{0}] = @{1}", property.Name, property.Name);
adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336
if (i < nonIdProps.Count() - 1)
sb.AppendFormat(", ");
}
......@@ -354,7 +376,7 @@ private static string GetTableName(Type type)
for (var i = 0; i < keyProperties.Count(); i++)
{
var property = keyProperties.ElementAt(i);
sb.AppendFormat("[{0}] = @{1}", property.Name, property.Name);
adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336
if (i < keyProperties.Count() - 1)
sb.AppendFormat(" and ");
}
......@@ -380,18 +402,22 @@ private static string GetTableName(Type type)
type = type.GetGenericArguments()[0];
var keyProperties = KeyPropertiesCache(type);
if (!keyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] property");
var explicitKeyProperties = ExplicitKeyPropertiesCache(type);
if (!keyProperties.Any() && !explicitKeyProperties.Any())
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
var name = GetTableName(type);
keyProperties.AddRange(explicitKeyProperties);
var sb = new StringBuilder();
sb.AppendFormat("delete from {0} where ", name);
var adapter = GetFormatter(connection);
for (var i = 0; i < keyProperties.Count(); i++)
{
var property = keyProperties.ElementAt(i);
sb.AppendFormat("[{0}] = @{1}", property.Name, property.Name);
adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336
if (i < keyProperties.Count() - 1)
sb.AppendFormat(" and ");
}
......@@ -609,6 +635,11 @@ public class KeyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class ExplicitKeyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class WriteAttribute : Attribute
{
......@@ -628,27 +659,41 @@ public class ComputedAttribute : Attribute
public partial interface ISqlAdapter
{
int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert);
//new methods for issue #336
void AppendColumnName(StringBuilder sb, string columnName);
void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
}
public partial class SqlServerAdapter : ISqlAdapter
{
public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = String.Format("insert into {0} ({1}) values ({2});select SCOPE_IDENTITY() id", tableName, columnList, parameterList);
var multi = connection.QueryMultiple(cmd,entityToInsert , transaction, commandTimeout);
var multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout);
var id = (int)multi.Read().First().id;
var first = multi.Read().FirstOrDefault();
if (first == null || first.id == null) return 0;
var id = (int)first.id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!propertyInfos.Any()) return id;
var idProperty = propertyInfos.First();
if (idProperty.PropertyType.Name == "Int16") //for short id/key types issue #196
idProperty.SetValue(entityToInsert, (Int16)id, null);
else
idProperty.SetValue(entityToInsert, id, null);
idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
return id;
}
public void AppendColumnName(StringBuilder sb, string columnName)
{
sb.AppendFormat("[{0}]", columnName);
}
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{
sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
}
}
public partial class SqlCeServerAdapter : ISqlAdapter
......@@ -657,19 +702,58 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
{
var cmd = String.Format("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
var r = connection.Query("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout);
var r = connection.Query("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ToList();
if (r.First().id == null) return 0;
var id = (int) r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!propertyInfos.Any()) return id;
var idProperty = propertyInfos.First();
idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
return id;
}
public void AppendColumnName(StringBuilder sb, string columnName)
{
sb.AppendFormat("[{0}]", columnName);
}
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{
sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
}
}
public partial class MySqlAdapter : ISqlAdapter
{
public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = String.Format("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
var r = connection.Query("Select LAST_INSERT_ID()", transaction: transaction, commandTimeout: commandTimeout);
var id = r.First().id;
if (id == null) return 0;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any())
{
var idProperty = propertyInfos.First();
if (idProperty.PropertyType.Name == "Int16") //for short id/key types issue #196
idProperty.SetValue(entityToInsert, (Int16)id, null);
else
idProperty.SetValue(entityToInsert, (int)id, null);
}
return (int)id;
if (!propertyInfos.Any()) return id;
var idp = propertyInfos.First();
idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
return id;
}
public void AppendColumnName(StringBuilder sb, string columnName)
{
sb.AppendFormat("`{0}`", columnName);
}
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{
sb.AppendFormat("`{0}` = @{1}", columnName, columnName);
}
}
......@@ -711,6 +795,16 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
}
return id;
}
public void AppendColumnName(StringBuilder sb, string columnName)
{
sb.AppendFormat("\"{0}\"", columnName);
}
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{
sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
}
}
public partial class SQLiteAdapter : ISqlAdapter
......@@ -718,12 +812,25 @@ public partial class SQLiteAdapter : ISqlAdapter
public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = String.Format("insert into {0} ({1}) values ({2}); select last_insert_rowid() id", tableName, columnList, parameterList);
var r = connection.Query(cmd, entityToInsert, transaction: transaction, commandTimeout: commandTimeout);
var id = (int)r.First().id;
var multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout);
var id = (int)multi.Read().First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any())
propertyInfos.First().SetValue(entityToInsert, id, null);
if (!propertyInfos.Any()) return id;
var idProperty = propertyInfos.First();
idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
return id;
}
public void AppendColumnName(StringBuilder sb, string columnName)
{
sb.AppendFormat("\"{0}\"", columnName);
}
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{
sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
}
}
......@@ -61,8 +61,13 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.EntityFramework NET45 SNK", "Dapper.EntityFramework NET45 SNK\Dapper.EntityFramework NET45 SNK.csproj", "{7169A2C1-F57E-4288-B22D-52394DD2EC06}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.SqlBuilder NET45", "Dapper.SqlBuilder NET45\Dapper.SqlBuilder NET45.csproj", "{B83D86B2-79C0-46AA-B51B-03730256FAAC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.SqlBuilder NET35", "Dapper.SqlBuilder NET35\Dapper.SqlBuilder NET35.csproj", "{13A52642-B160-4050-A101-F64FABE7AF9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.Contrib.MsSqlTests NET45", "Dapper.Contrib.MsSqlTests NET45\Dapper.Contrib.MsSqlTests NET45.csproj", "{E5482A3B-2C2A-4907-9804-C191F18FA622}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.Contrib.SqliteTests NET45", "Dapper.Contrib.SqliteTests NET45\Dapper.Contrib.SqliteTests NET45.csproj", "{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -293,6 +298,26 @@ Global
{13A52642-B160-4050-A101-F64FABE7AF9D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{13A52642-B160-4050-A101-F64FABE7AF9D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{13A52642-B160-4050-A101-F64FABE7AF9D}.Release|x86.ActiveCfg = Release|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Debug|x86.ActiveCfg = Debug|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Release|Any CPU.Build.0 = Release|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E5482A3B-2C2A-4907-9804-C191F18FA622}.Release|x86.ActiveCfg = Release|Any CPU
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Debug|Any CPU.ActiveCfg = Debug|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Debug|Mixed Platforms.Build.0 = Debug|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Debug|x86.ActiveCfg = Debug|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Debug|x86.Build.0 = Debug|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Release|Any CPU.ActiveCfg = Release|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Release|Mixed Platforms.ActiveCfg = Release|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Release|Mixed Platforms.Build.0 = Release|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Release|x86.ActiveCfg = Release|x86
{114C32A1-D726-4F64-B8AF-AFEDE728E0BC}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册