Commit 984055aa authored by johandanforth's avatar johandanforth

Specific insert adapters for sql/sql ce. Faster inserts for sql server now

parent 6170b55c
......@@ -291,6 +291,37 @@ public partial interface ISqlAdapter
}
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 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 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;
}
}
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)
{
......@@ -298,7 +329,6 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
//NOTE: would prefer to use IDENT_CURRENT('tablename') or IDENT_SCOPE but these are not available on SQLCE
var r = await connection.QueryAsync<dynamic>("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
var id = (int)r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
......
......@@ -31,6 +31,7 @@ private static void Setup()
using (var connection = new SqlCeConnection(connectionString))
{
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) ");
......
......@@ -6,7 +6,7 @@
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Dapper;
using Dapper.Contrib.Extensions;
namespace Dapper.Contrib.Tests
......@@ -87,7 +87,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 SqlServerAdapter())).IsMoreThan(0);
(await connection.InsertAsync(new User { Name = "Adam", Age = 10 }, sqlAdapter: new SqlCeServerAdapter())).IsMoreThan(0);
}
}
......
......@@ -2,12 +2,11 @@
using System.Collections.Generic;
using System.Data;
using System.Data.SqlServerCe;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Transactions;
using Dapper;
using Dapper.Contrib.Extensions;
namespace Dapper.Contrib.Tests
......@@ -264,7 +263,7 @@ public void InsertWithCustomDbType()
}
catch (SqlCeException ex)
{
sqliteCodeCalled = ex.Message.IndexOf("last_insert_rowid", StringComparison.InvariantCultureIgnoreCase) >= 0;
sqliteCodeCalled = ex.Message.IndexOf("There was an error parsing the query", StringComparison.InvariantCultureIgnoreCase) >= 0;
}
catch (Exception)
{
......@@ -288,6 +287,10 @@ public void InsertWithCustomTableNameMapper()
case "Person":
return "People";
default:
var tableattr = type.GetCustomAttributes(false).SingleOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic;
if (tableattr != null)
return tableattr.Name;
var name = type.Name + "s";
if (type.IsInterface && name.StartsWith("I"))
name = name.Substring(1);
......
......@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Dapper.Contrib</id>
<version>1.42</version>
<version>1.44</version>
<authors>Sam Saffron,Johan Danforth</authors>
<owners>Johan Danforth, Marc Gravell</owners>
<licenseUrl>http://www.apache.org/licenses/LICENSE-2.0</licenseUrl>
......@@ -11,6 +11,8 @@
<description>The official collection of get, insert, update and delete helpers for dapper.net. Also handles lists of entities and optional "dirty" tracking of interface-based entities.</description>
<tags>orm sql micro-orm dapper</tags>
<releaseNotes>
* 1.44 - Specific insert adapters for sql/sql ce. Faster inserts for sql server now
* 1.43 - GetDatebaseType delegate for Insert, TableNameMapper, Insert now handles closed connection and supports short/int16 id/key
* 1.42 - InsertAsync() UpdateAsync() and DeleteAsync() now also handles lists of entities (.NET 4.5 only)
* 1.41 - added GetAll(). Insert() Update() and Delete() now handles lists of entities!
* 1.40 - cumulative changes up to dapper 1.40; will track changes more carefully subsequently
......
......@@ -39,6 +39,7 @@ public interface ITableNameMapper
private static readonly Dictionary<string, ISqlAdapter> AdapterDictionary = new Dictionary<string, ISqlAdapter> {
{"sqlconnection", new SqlServerAdapter()},
{"sqlceconnection", new SqlCeServerAdapter()},
{"npgsqlconnection", new PostgresAdapter()},
{"sqliteconnection", new SQLiteAdapter()}
};
......@@ -633,15 +634,31 @@ 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)
{
//TODO: Append a select identity at end if command?
//TODO: Create specific sqladapter for sqlce
var cmd = String.Format("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
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);
connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
var id = (int)multi.Read().First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (!propertyInfos.Any()) return id;
//TODO: use IDENT_CURRENT('tablename') or IDENT_SCOPE or SCOPE_IDENTITY() - create specific sqlce adapter with @@IDENTITY
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;
}
}
public partial class SqlCeServerAdapter : 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 @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout);
var id = r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any())
......@@ -700,11 +717,8 @@ 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})", tableName, columnList, parameterList);
connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
var r = connection.Query("select last_insert_rowid() id", transaction: transaction, commandTimeout: commandTimeout);
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 propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment