diff --git a/Dapper.sln b/Dapper.sln
index e993c7a4..4aa75f10 100644
--- a/Dapper.sln
+++ b/Dapper.sln
@@ -16,7 +16,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
version.json = version.json
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Contrib", "Dapper.Contrib\Dapper.Contrib.csproj", "{4E409F8F-CFBB-4332-8B0A-FD5A283051FD}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Contrib", "src\Dapper.Contrib\Dapper.Contrib.csproj", "{4E409F8F-CFBB-4332-8B0A-FD5A283051FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests.Contrib", "tests\Dapper.Tests.Contrib\Dapper.Tests.Contrib.csproj", "{DAB3C5B7-BCD1-4A5F-BB6B-50D2BB63DB4A}"
EndProject
diff --git a/src/Dapper.Contrib/Adapters.cs b/src/Dapper.Contrib/Adapters.cs
new file mode 100644
index 00000000..4d384a85
--- /dev/null
+++ b/src/Dapper.Contrib/Adapters.cs
@@ -0,0 +1,894 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Dapper.Contrib
+{
+ ///
+ /// The interface for all Dapper.Contrib database operations
+ /// Implementing this is each provider's model.
+ ///
+ public partial interface ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert);
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ string GetColumnWithNotation(string columnName);
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ void AppendColumnName(StringBuilder sb, string columnName);
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ void AppendColumnValue(StringBuilder sb, string columnName);
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
+ }
+
+ ///
+ /// The SQL Server database adapter.
+ ///
+ public partial class SqlServerAdapter : ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"insert into {tableName} ({columnList}) values ({parameterList});select SCOPE_IDENTITY() id";
+ var multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout);
+
+ 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.Length == 0) return id;
+
+ var idProperty = propertyInfos[0];
+ idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
+
+ return id;
+ }
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ public string GetColumnWithNotation(string columnName)
+ {
+ return String.Format("@{0}", columnName);
+ }
+
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnName(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("[{0}]", columnName);
+ }
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("@{0}", columnName);
+ }
+
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
+ }
+ }
+
+ ///
+ /// The SQL Server Compact Edition database adapter.
+ ///
+ public partial class SqlCeServerAdapter : ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
+ connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
+ var r = connection.Query("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ToList();
+
+ if (r[0].id == null) return 0;
+ var id = (int)r[0].id;
+
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ if (propertyInfos.Length == 0) return id;
+
+ var idProperty = propertyInfos[0];
+ idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
+
+ return id;
+ }
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ public string GetColumnWithNotation(string columnName)
+ {
+ return String.Format("@{0}", columnName);
+ }
+
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnName(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("[{0}]", columnName);
+ }
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("@{0}", columnName);
+ }
+
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
+ }
+ }
+
+ ///
+ /// The MySQL database adapter.
+ ///
+ public partial class MySqlAdapter : ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
+ connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
+ var r = connection.Query("Select LAST_INSERT_ID() id", transaction: transaction, commandTimeout: commandTimeout);
+
+ var id = r.First().id;
+ if (id == null) return 0;
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ if (propertyInfos.Length == 0) return Convert.ToInt32(id);
+
+ var idp = propertyInfos[0];
+ idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
+
+ return Convert.ToInt32(id);
+ }
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ public string GetColumnWithNotation(string columnName)
+ {
+ return String.Format("@{0}", columnName);
+ }
+
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnName(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("`{0}`", columnName);
+ }
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("@{0}", columnName);
+ }
+
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("`{0}` = @{1}", columnName, columnName);
+ }
+ }
+
+ ///
+ /// The Postgres database adapter.
+ ///
+ public partial class PostgresAdapter : ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var sb = new StringBuilder();
+ sb.AppendFormat("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
+
+ // If no primary key then safe to assume a join table with not too much data to return
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ if (propertyInfos.Length == 0)
+ {
+ sb.Append(" RETURNING *");
+ }
+ else
+ {
+ sb.Append(" RETURNING ");
+ var first = true;
+ foreach (var property in propertyInfos)
+ {
+ if (!first)
+ sb.Append(", ");
+ first = false;
+ sb.Append(property.Name);
+ }
+ }
+
+ var results = connection.Query(sb.ToString(), entityToInsert, transaction, commandTimeout: commandTimeout).ToList();
+
+ // Return the key by assigning the corresponding property in the object - by product is that it supports compound primary keys
+ var id = 0;
+ foreach (var p in propertyInfos)
+ {
+ var value = ((IDictionary)results[0])[p.Name.ToLower()];
+ p.SetValue(entityToInsert, value, null);
+ if (id == 0)
+ id = Convert.ToInt32(value);
+ }
+ return id;
+ }
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ public string GetColumnWithNotation(string columnName)
+ {
+ return String.Format("@{0}", columnName);
+ }
+
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnName(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("\"{0}\"", columnName);
+ }
+
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("@{0}", columnName);
+ }
+
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
+ }
+ }
+
+ ///
+ /// The SQLite database adapter.
+ ///
+ public partial class SQLiteAdapter : ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() 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.Length == 0) return id;
+
+ var idProperty = propertyInfos[0];
+ idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
+
+ return id;
+ }
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ public string GetColumnWithNotation(string columnName)
+ {
+ return String.Format("@{0}", columnName);
+ }
+
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnName(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("\"{0}\"", columnName);
+ }
+
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("@{0}", columnName);
+ }
+
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
+ }
+ }
+
+ ///
+ /// The Firebase SQL adapter.
+ ///
+ public partial class FbAdapter : ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
+ connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
+
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ var keyName = propertyInfos[0].Name;
+ var r = connection.Query($"SELECT FIRST 1 {keyName} ID FROM {tableName} ORDER BY {keyName} DESC", transaction: transaction, commandTimeout: commandTimeout);
+
+ var id = r.First().ID;
+ if (id == null) return 0;
+ if (propertyInfos.Length == 0) return Convert.ToInt32(id);
+
+ var idp = propertyInfos[0];
+ idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
+
+ return Convert.ToInt32(id);
+ }
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ public string GetColumnWithNotation(string columnName)
+ {
+ return String.Format("@{0}", columnName);
+ }
+
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnName(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("{0}", columnName);
+ }
+
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("@{0}", columnName);
+ }
+
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("{0} = @{1}", columnName, columnName);
+ }
+ }
+
+ ///
+ /// The OleDb database adapter.
+ ///
+ public partial class OleDbAdapter : ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var sb = new StringBuilder();
+ sb.AppendFormat("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
+
+ // If no primary key then safe to assume a join table with not too much data to return
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+
+ sb.Append(" select @@identity ");
+ var first = true;
+ foreach (var property in propertyInfos)
+ {
+ if (!first)
+ sb.Append(", ");
+ first = false;
+ sb.Append(property.Name);
+ }
+
+
+ var results = connection.Query(sb.ToString(), entityToInsert, transaction, commandTimeout: commandTimeout).ToList();
+
+ // Return the key by assigning the corresponding property in the object - by product is that it supports compound primary keys
+ var id = 0;
+ foreach (var p in propertyInfos)
+ {
+ var value = ((IDictionary)results[0])[p.Name];
+ p.SetValue(entityToInsert, Convert.ChangeType(value, p.PropertyType), null);
+ if (id == 0)
+ id = Convert.ToInt32(value);
+ }
+ return id;
+ }
+
+ ///
+ /// Get column with correct notation.
+ ///
+ /// The column name.
+ public string GetColumnWithNotation(string columnName)
+ {
+ return String.Format("?{0}?", columnName);
+ }
+
+ ///
+ /// Adds the name of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnName(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("[{0}]", columnName);
+ }
+
+ ///
+ /// Adds the value of a column.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("?{0}?", columnName);
+ }
+
+ ///
+ /// Adds a column equality to a parameter.
+ ///
+ /// The string builder to append to.
+ /// The column name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ {
+ sb.AppendFormat("[{0}] = ?{1}?", columnName, columnName);
+ }
+ }
+
+ public partial interface ISqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert);
+ }
+
+ public partial class SqlServerAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"INSERT INTO {tableName} ({columnList}) values ({parameterList}); SELECT SCOPE_IDENTITY() id";
+ var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
+
+ var first = await multi.ReadFirstOrDefaultAsync().ConfigureAwait(false);
+ if (first == null || first.id == null) return 0;
+
+ var id = (int)first.id;
+ var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ if (pi.Length == 0) return id;
+
+ var idp = pi[0];
+ idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
+
+ return id;
+ }
+ }
+
+ public partial class SqlCeServerAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList})";
+ await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
+ var r = (await connection.QueryAsync("SELECT @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false)).ToList();
+
+ if (r[0] == null || r[0].id == null) return 0;
+ var id = (int)r[0].id;
+
+ var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ if (pi.Length == 0) return id;
+
+ var idp = pi[0];
+ idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
+
+ return id;
+ }
+ }
+
+ public partial class MySqlAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName,
+ string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList})";
+ await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
+ var r = await connection.QueryAsync("SELECT LAST_INSERT_ID() 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.Length == 0) return Convert.ToInt32(id);
+
+ var idp = pi[0];
+ idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
+
+ return Convert.ToInt32(id);
+ }
+ }
+
+ public partial class PostgresAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var sb = new StringBuilder();
+ sb.AppendFormat("INSERT INTO {0} ({1}) VALUES ({2})", tableName, columnList, parameterList);
+
+ // If no primary key then safe to assume a join table with not too much data to return
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ if (propertyInfos.Length == 0)
+ {
+ sb.Append(" RETURNING *");
+ }
+ else
+ {
+ sb.Append(" RETURNING ");
+ bool first = true;
+ foreach (var property in propertyInfos)
+ {
+ if (!first)
+ sb.Append(", ");
+ first = false;
+ sb.Append(property.Name);
+ }
+ }
+
+ var results = await connection.QueryAsync(sb.ToString(), entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
+
+ // Return the key by assigning the corresponding property in the object - by product is that it supports compound primary keys
+ var id = 0;
+ foreach (var p in propertyInfos)
+ {
+ var value = ((IDictionary)results.First())[p.Name.ToLower()];
+ p.SetValue(entityToInsert, value, null);
+ if (id == 0)
+ id = Convert.ToInt32(value);
+ }
+ return id;
+ }
+ }
+
+ public partial class SQLiteAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id";
+ var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
+
+ var id = (int)(await multi.ReadFirstAsync().ConfigureAwait(false)).id;
+ var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ if (pi.Length == 0) return id;
+
+ var idp = pi[0];
+ idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
+
+ return id;
+ }
+ }
+
+ public partial class FbAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
+ await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
+
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+ var keyName = propertyInfos[0].Name;
+ var r = await connection.QueryAsync($"SELECT FIRST 1 {keyName} ID FROM {tableName} ORDER BY {keyName} DESC", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
+
+ var id = r.First().ID;
+ if (id == null) return 0;
+ if (propertyInfos.Length == 0) return Convert.ToInt32(id);
+
+ var idp = propertyInfos[0];
+ idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
+
+ return Convert.ToInt32(id);
+ }
+ }
+
+ public partial class OleDbAdapter
+ {
+ ///
+ /// Inserts into the database, returning the Id of the row created.
+ ///
+ /// The connection to use.
+ /// The transaction to use.
+ /// The command timeout to use.
+ /// The table to insert into.
+ /// The columns to set with this insert.
+ /// The parameters to set for this insert.
+ /// The key columns in this table.
+ /// The entity to insert.
+ /// The Id of the row created.
+ public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
+ {
+ var sb = new StringBuilder();
+ sb.AppendFormat("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
+
+ // If no primary key then safe to assume a join table with not too much data to return
+ var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
+
+ sb.Append(" select @@identity ");
+ var first = true;
+ foreach (var property in propertyInfos)
+ {
+ if (!first)
+ sb.Append(", ");
+ first = false;
+ sb.Append(property.Name);
+ }
+
+
+ var results = connection.Query(sb.ToString(), entityToInsert, transaction, commandTimeout: commandTimeout).ToList();
+
+ // Return the key by assigning the corresponding property in the object - by product is that it supports compound primary keys
+ var id = 0;
+ foreach (var p in propertyInfos)
+ {
+ var value = ((IDictionary)results[0])[p.Name];
+ p.SetValue(entityToInsert, Convert.ChangeType(value, p.PropertyType), null);
+ if (id == 0)
+ id = Convert.ToInt32(value);
+ }
+ return id;
+ }
+ }
+
+ public class Adapters
+ {
+ }
+}
diff --git a/src/Dapper.Contrib/SqlMapperExtensions.Async.cs b/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
index c93e39a4..9257378e 100644
--- a/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
+++ b/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
@@ -24,18 +24,22 @@ public static partial class SqlMapperExtensions
/// Entity of T
public static async Task GetAsync(this IDbConnection connection, dynamic id, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
{
+ var adapter = GetFormatter(connection);
+
var type = typeof(T);
+ var idParameter = adapter.GetColumnWithNotation("id");
+
if (!GetQueries.TryGetValue(type.TypeHandle, out string sql))
{
var key = GetSingleKey(nameof(GetAsync));
var name = GetTableName(type);
- sql = $"SELECT * FROM {name} WHERE {key.Name} = @id";
+ sql = $"SELECT * FROM {name} WHERE {key.Name} = {idParameter}";
GetQueries[type.TypeHandle] = sql;
}
var dynParams = new DynamicParameters();
- dynParams.Add("@id", id);
+ dynParams.Add("id", id);
if (!type.IsInterface)
return (await connection.QueryAsync(sql, dynParams, transaction, commandTimeout).ConfigureAwait(false)).FirstOrDefault();
@@ -181,7 +185,7 @@ public static Task InsertAsync(this IDbConnection connection, T entityTo
for (var i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++)
{
var property = allPropertiesExceptKeyAndComputed[i];
- sbParameterList.AppendFormat("@{0}", property.Name);
+ sqlAdapter.AppendColumnValue(sbParameterList, property.Name);
if (i < allPropertiesExceptKeyAndComputed.Count - 1)
sbParameterList.Append(", ");
}
@@ -342,236 +346,3 @@ public static async Task DeleteAllAsync(this IDbConnection connection,
}
}
}
-
-public partial interface ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert);
-}
-
-public partial class SqlServerAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"INSERT INTO {tableName} ({columnList}) values ({parameterList}); SELECT SCOPE_IDENTITY() id";
- var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
-
- var first = await multi.ReadFirstOrDefaultAsync().ConfigureAwait(false);
- if (first == null || first.id == null) return 0;
-
- var id = (int)first.id;
- var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- if (pi.Length == 0) return id;
-
- var idp = pi[0];
- idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
-
- return id;
- }
-}
-
-public partial class SqlCeServerAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList})";
- await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
- var r = (await connection.QueryAsync("SELECT @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false)).ToList();
-
- if (r[0] == null || r[0].id == null) return 0;
- var id = (int)r[0].id;
-
- var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- if (pi.Length == 0) return id;
-
- var idp = pi[0];
- idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
-
- return id;
- }
-}
-
-public partial class MySqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName,
- string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList})";
- await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
- var r = await connection.QueryAsync("SELECT LAST_INSERT_ID() 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.Length == 0) return Convert.ToInt32(id);
-
- var idp = pi[0];
- idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
-
- return Convert.ToInt32(id);
- }
-}
-
-public partial class PostgresAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var sb = new StringBuilder();
- sb.AppendFormat("INSERT INTO {0} ({1}) VALUES ({2})", tableName, columnList, parameterList);
-
- // If no primary key then safe to assume a join table with not too much data to return
- var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- if (propertyInfos.Length == 0)
- {
- sb.Append(" RETURNING *");
- }
- else
- {
- sb.Append(" RETURNING ");
- bool first = true;
- foreach (var property in propertyInfos)
- {
- if (!first)
- sb.Append(", ");
- first = false;
- sb.Append(property.Name);
- }
- }
-
- var results = await connection.QueryAsync(sb.ToString(), entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
-
- // Return the key by assigning the corresponding property in the object - by product is that it supports compound primary keys
- var id = 0;
- foreach (var p in propertyInfos)
- {
- var value = ((IDictionary)results.First())[p.Name.ToLower()];
- p.SetValue(entityToInsert, value, null);
- if (id == 0)
- id = Convert.ToInt32(value);
- }
- return id;
- }
-}
-
-public partial class SQLiteAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id";
- var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
-
- var id = (int)(await multi.ReadFirstAsync().ConfigureAwait(false)).id;
- var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- if (pi.Length == 0) return id;
-
- var idp = pi[0];
- idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
-
- return id;
- }
-}
-
-public partial class FbAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public async Task InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
- await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
-
- var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- var keyName = propertyInfos[0].Name;
- var r = await connection.QueryAsync($"SELECT FIRST 1 {keyName} ID FROM {tableName} ORDER BY {keyName} DESC", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
-
- var id = r.First().ID;
- if (id == null) return 0;
- if (propertyInfos.Length == 0) return Convert.ToInt32(id);
-
- var idp = propertyInfos[0];
- idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
-
- return Convert.ToInt32(id);
- }
-}
diff --git a/src/Dapper.Contrib/SqlMapperExtensions.cs b/src/Dapper.Contrib/SqlMapperExtensions.cs
index 9a30e805..17432f95 100644
--- a/src/Dapper.Contrib/SqlMapperExtensions.cs
+++ b/src/Dapper.Contrib/SqlMapperExtensions.cs
@@ -9,6 +9,7 @@
using System.Threading;
using Dapper;
+using System.Data.Common;
namespace Dapper.Contrib.Extensions
{
@@ -61,14 +62,15 @@ public interface ITableNameMapper
private static readonly ISqlAdapter DefaultAdapter = new SqlServerAdapter();
private static readonly Dictionary AdapterDictionary
- = new Dictionary(6)
+ = new Dictionary(7)
{
["sqlconnection"] = new SqlServerAdapter(),
["sqlceconnection"] = new SqlCeServerAdapter(),
["npgsqlconnection"] = new PostgresAdapter(),
["sqliteconnection"] = new SQLiteAdapter(),
["mysqlconnection"] = new MySqlAdapter(),
- ["fbconnection"] = new FbAdapter()
+ ["fbconnection"] = new FbAdapter(),
+ ["oledbconnection"] = new OleDbAdapter()
};
private static List ComputedPropertiesCache(Type type)
@@ -169,19 +171,24 @@ private static PropertyInfo GetSingleKey(string method)
/// Entity of T
public static T Get(this IDbConnection connection, dynamic id, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
{
+ var adapter = GetFormatter(connection);
+
var type = typeof(T);
+ var idParameter = adapter.GetColumnWithNotation("id");
if (!GetQueries.TryGetValue(type.TypeHandle, out string sql))
{
var key = GetSingleKey(nameof(Get));
var name = GetTableName(type);
-
- sql = $"select * from {name} where {key.Name} = @id";
+ sql = $"select * from {name} where {key.Name} = {idParameter}";
GetQueries[type.TypeHandle] = sql;
}
var dynParams = new DynamicParameters();
- dynParams.Add("@id", id);
+ //sbParameterList.AppendFormat("@{0}", property.Name);
+
+ //Extra '?' because Dapper Trims the first '?'
+ dynParams.Add(string.Format("?{0}", idParameter), id);
T obj;
@@ -363,7 +370,7 @@ public static long Insert(this IDbConnection connection, T entityToInsert, ID
for (var i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++)
{
var property = allPropertiesExceptKeyAndComputed[i];
- sbParameterList.AppendFormat("@{0}", property.Name);
+ adapter.AppendColumnValue(sbParameterList, property.Name);
if (i < allPropertiesExceptKeyAndComputed.Count - 1)
sbParameterList.Append(", ");
}
@@ -766,390 +773,3 @@ public class ComputedAttribute : Attribute
{
}
}
-
-///
-/// The interface for all Dapper.Contrib database operations
-/// Implementing this is each provider's model.
-///
-public partial interface ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert);
-
- ///
- /// Adds the name of a column.
- ///
- /// The string builder to append to.
- /// The column name.
- void AppendColumnName(StringBuilder sb, string columnName);
- ///
- /// Adds a column equality to a parameter.
- ///
- /// The string builder to append to.
- /// The column name.
- void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
-}
-
-///
-/// The SQL Server database adapter.
-///
-public partial class SqlServerAdapter : ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"insert into {tableName} ({columnList}) values ({parameterList});select SCOPE_IDENTITY() id";
- var multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout);
-
- 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.Length == 0) return id;
-
- var idProperty = propertyInfos[0];
- idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
-
- return id;
- }
-
- ///
- /// Adds the name of a column.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("[{0}]", columnName);
- }
-
- ///
- /// Adds a column equality to a parameter.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
- }
-}
-
-///
-/// The SQL Server Compact Edition database adapter.
-///
-public partial class SqlCeServerAdapter : ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
- connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
- var r = connection.Query("select @@IDENTITY id", transaction: transaction, commandTimeout: commandTimeout).ToList();
-
- if (r[0].id == null) return 0;
- var id = (int)r[0].id;
-
- var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- if (propertyInfos.Length == 0) return id;
-
- var idProperty = propertyInfos[0];
- idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
-
- return id;
- }
-
- ///
- /// Adds the name of a column.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("[{0}]", columnName);
- }
-
- ///
- /// Adds a column equality to a parameter.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
- }
-}
-
-///
-/// The MySQL database adapter.
-///
-public partial class MySqlAdapter : ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
- connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
- var r = connection.Query("Select LAST_INSERT_ID() id", transaction: transaction, commandTimeout: commandTimeout);
-
- var id = r.First().id;
- if (id == null) return 0;
- var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- if (propertyInfos.Length == 0) return Convert.ToInt32(id);
-
- var idp = propertyInfos[0];
- idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
-
- return Convert.ToInt32(id);
- }
-
- ///
- /// Adds the name of a column.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("`{0}`", columnName);
- }
-
- ///
- /// Adds a column equality to a parameter.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("`{0}` = @{1}", columnName, columnName);
- }
-}
-
-///
-/// The Postgres database adapter.
-///
-public partial class PostgresAdapter : ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var sb = new StringBuilder();
- sb.AppendFormat("insert into {0} ({1}) values ({2})", tableName, columnList, parameterList);
-
- // If no primary key then safe to assume a join table with not too much data to return
- var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- if (propertyInfos.Length == 0)
- {
- sb.Append(" RETURNING *");
- }
- else
- {
- sb.Append(" RETURNING ");
- var first = true;
- foreach (var property in propertyInfos)
- {
- if (!first)
- sb.Append(", ");
- first = false;
- sb.Append(property.Name);
- }
- }
-
- var results = connection.Query(sb.ToString(), entityToInsert, transaction, commandTimeout: commandTimeout).ToList();
-
- // Return the key by assigning the corresponding property in the object - by product is that it supports compound primary keys
- var id = 0;
- foreach (var p in propertyInfos)
- {
- var value = ((IDictionary)results[0])[p.Name.ToLower()];
- p.SetValue(entityToInsert, value, null);
- if (id == 0)
- id = Convert.ToInt32(value);
- }
- return id;
- }
-
- ///
- /// Adds the name of a column.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("\"{0}\"", columnName);
- }
-
- ///
- /// Adds a column equality to a parameter.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
- }
-}
-
-///
-/// The SQLite database adapter.
-///
-public partial class SQLiteAdapter : ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() 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.Length == 0) return id;
-
- var idProperty = propertyInfos[0];
- idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
-
- return id;
- }
-
- ///
- /// Adds the name of a column.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("\"{0}\"", columnName);
- }
-
- ///
- /// Adds a column equality to a parameter.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
- }
-}
-
-///
-/// The Firebase SQL adapter.
-///
-public partial class FbAdapter : ISqlAdapter
-{
- ///
- /// Inserts into the database, returning the Id of the row created.
- ///
- /// The connection to use.
- /// The transaction to use.
- /// The command timeout to use.
- /// The table to insert into.
- /// The columns to set with this insert.
- /// The parameters to set for this insert.
- /// The key columns in this table.
- /// The entity to insert.
- /// The Id of the row created.
- public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable keyProperties, object entityToInsert)
- {
- var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
- connection.Execute(cmd, entityToInsert, transaction, commandTimeout);
-
- var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
- var keyName = propertyInfos[0].Name;
- var r = connection.Query($"SELECT FIRST 1 {keyName} ID FROM {tableName} ORDER BY {keyName} DESC", transaction: transaction, commandTimeout: commandTimeout);
-
- var id = r.First().ID;
- if (id == null) return 0;
- if (propertyInfos.Length == 0) return Convert.ToInt32(id);
-
- var idp = propertyInfos[0];
- idp.SetValue(entityToInsert, Convert.ChangeType(id, idp.PropertyType), null);
-
- return Convert.ToInt32(id);
- }
-
- ///
- /// Adds the name of a column.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("{0}", columnName);
- }
-
- ///
- /// Adds a column equality to a parameter.
- ///
- /// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
- {
- sb.AppendFormat("{0} = @{1}", columnName, columnName);
- }
-}