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 ...@@ -291,6 +291,37 @@ public partial interface ISqlAdapter
} }
public partial class SqlServerAdapter 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) 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 ...@@ -298,7 +329,6 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false); 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 r = await connection.QueryAsync<dynamic>("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
var id = (int)r.First().id; var id = (int)r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
......
...@@ -31,6 +31,7 @@ private static void Setup() ...@@ -31,6 +31,7 @@ private static void Setup()
using (var connection = new SqlCeConnection(connectionString)) using (var connection = new SqlCeConnection(connectionString))
{ {
connection.Open(); 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 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 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 Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) ");
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dapper;
using Dapper.Contrib.Extensions; using Dapper.Contrib.Extensions;
namespace Dapper.Contrib.Tests namespace Dapper.Contrib.Tests
...@@ -87,7 +87,7 @@ public async Task InsertGetUpdateAsync() ...@@ -87,7 +87,7 @@ public async Task InsertGetUpdateAsync()
(await connection.UpdateAsync(notrackedUser)).IsEqualTo(false); //returns false, user not found (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 @@ ...@@ -2,12 +2,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.SqlServerCe; using System.Data.SqlServerCe;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Transactions; using System.Transactions;
using Dapper;
using Dapper.Contrib.Extensions; using Dapper.Contrib.Extensions;
namespace Dapper.Contrib.Tests namespace Dapper.Contrib.Tests
...@@ -264,7 +263,7 @@ public void InsertWithCustomDbType() ...@@ -264,7 +263,7 @@ public void InsertWithCustomDbType()
} }
catch (SqlCeException ex) 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) catch (Exception)
{ {
...@@ -288,6 +287,10 @@ public void InsertWithCustomTableNameMapper() ...@@ -288,6 +287,10 @@ public void InsertWithCustomTableNameMapper()
case "Person": case "Person":
return "People"; return "People";
default: 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"; var name = type.Name + "s";
if (type.IsInterface && name.StartsWith("I")) if (type.IsInterface && name.StartsWith("I"))
name = name.Substring(1); name = name.Substring(1);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>Dapper.Contrib</id> <id>Dapper.Contrib</id>
<version>1.42</version> <version>1.44</version>
<authors>Sam Saffron,Johan Danforth</authors> <authors>Sam Saffron,Johan Danforth</authors>
<owners>Johan Danforth, Marc Gravell</owners> <owners>Johan Danforth, Marc Gravell</owners>
<licenseUrl>http://www.apache.org/licenses/LICENSE-2.0</licenseUrl> <licenseUrl>http://www.apache.org/licenses/LICENSE-2.0</licenseUrl>
...@@ -11,6 +11,8 @@ ...@@ -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> <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> <tags>orm sql micro-orm dapper</tags>
<releaseNotes> <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.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.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 * 1.40 - cumulative changes up to dapper 1.40; will track changes more carefully subsequently
......
...@@ -39,6 +39,7 @@ public interface ITableNameMapper ...@@ -39,6 +39,7 @@ public interface ITableNameMapper
private static readonly Dictionary<string, ISqlAdapter> AdapterDictionary = new Dictionary<string, ISqlAdapter> { private static readonly Dictionary<string, ISqlAdapter> AdapterDictionary = new Dictionary<string, ISqlAdapter> {
{"sqlconnection", new SqlServerAdapter()}, {"sqlconnection", new SqlServerAdapter()},
{"sqlceconnection", new SqlCeServerAdapter()},
{"npgsqlconnection", new PostgresAdapter()}, {"npgsqlconnection", new PostgresAdapter()},
{"sqliteconnection", new SQLiteAdapter()} {"sqliteconnection", new SQLiteAdapter()}
}; };
...@@ -633,15 +634,31 @@ public partial class SqlServerAdapter : ISqlAdapter ...@@ -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) 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;
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;
}
}
//TODO: use IDENT_CURRENT('tablename') or IDENT_SCOPE or SCOPE_IDENTITY() - create specific sqlce adapter with @@IDENTITY 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 r = connection.Query("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout);
var id = r.First().id; var id = r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any()) if (propertyInfos.Any())
...@@ -700,11 +717,8 @@ public partial class SQLiteAdapter : ISqlAdapter ...@@ -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) 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); 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);
connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
var r = connection.Query("select last_insert_rowid() id", transaction: transaction, commandTimeout: commandTimeout);
var id = (int)r.First().id; var id = (int)r.First().id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray(); var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Any()) 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