Commit 4be8df79 authored by Nick Craver's avatar Nick Craver

Lots of documentation fixes/additions.

parent 7820ee2e
...@@ -306,11 +306,35 @@ public static partial class SqlMapperExtensions ...@@ -306,11 +306,35 @@ public static partial class SqlMapperExtensions
public partial interface ISqlAdapter public partial interface ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert); Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, String tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert);
} }
public partial class SqlServerAdapter public partial class SqlServerAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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)
{ {
var cmd = $"INSERT INTO {tableName} ({columnList}) values ({parameterList}); SELECT SCOPE_IDENTITY() id"; var cmd = $"INSERT INTO {tableName} ({columnList}) values ({parameterList}); SELECT SCOPE_IDENTITY() id";
...@@ -332,6 +356,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran ...@@ -332,6 +356,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
public partial class SqlCeServerAdapter public partial class SqlCeServerAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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)
{ {
var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList})"; var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList})";
...@@ -353,6 +389,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran ...@@ -353,6 +389,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
public partial class MySqlAdapter public partial class MySqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName,
string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert) string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{ {
...@@ -373,7 +421,19 @@ public partial class MySqlAdapter ...@@ -373,7 +421,19 @@ public partial class MySqlAdapter
} }
public partial class PostgresAdapter public partial class PostgresAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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)
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
...@@ -414,6 +474,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran ...@@ -414,6 +474,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
public partial class SQLiteAdapter public partial class SQLiteAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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)
{ {
var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id"; var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id";
...@@ -432,6 +504,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran ...@@ -432,6 +504,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
public partial class FbAdapter public partial class FbAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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)
{ {
var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})"; var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
......
...@@ -17,20 +17,44 @@ ...@@ -17,20 +17,44 @@
namespace Dapper.Contrib.Extensions namespace Dapper.Contrib.Extensions
{ {
/// <summary>
/// The Dapper.Contrib extensions for Dapper
/// </summary>
public static partial class SqlMapperExtensions public static partial class SqlMapperExtensions
{ {
// ReSharper disable once MemberCanBePrivate.Global /// <summary>
/// Defined a proxy object with a possibly dirty state.
/// </summary>
public interface IProxy //must be kept public public interface IProxy //must be kept public
{ {
/// <summary>
/// Whether the object has been changed.
/// </summary>
bool IsDirty { get; set; } bool IsDirty { get; set; }
} }
/// <summary>
/// Defines a table name mapper for getting table names from types.
/// </summary>
public interface ITableNameMapper public interface ITableNameMapper
{ {
/// <summary>
/// Gets a table name from a given <see cref="Type"/>.
/// </summary>
/// <param name="type">The <see cref="Type"/> to get a name from.</param>
/// <returns>The table name for the given <paramref name="type"/>.</returns>
string GetTableName(Type type); string GetTableName(Type type);
} }
/// <summary>
/// The function to get a database type from the given <see cref="IDbConnection"/>.
/// </summary>
/// <param name="connection">The connection to get a database type name from.</param>
public delegate string GetDatabaseTypeDelegate(IDbConnection connection); public delegate string GetDatabaseTypeDelegate(IDbConnection connection);
/// <summary>
/// The function to get a a table name from a given <see cref="Type"/>
/// </summary>
/// <param name="type">The <see cref="Type"/> to get a table name for.</param>
public delegate string TableNameMapperDelegate(Type type); 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>> KeyProperties = new ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>>();
...@@ -647,57 +671,124 @@ private static void CreateProperty<T>(TypeBuilder typeBuilder, string propertyNa ...@@ -647,57 +671,124 @@ private static void CreateProperty<T>(TypeBuilder typeBuilder, string propertyNa
} }
} }
/// <summary>
/// Defines the name of a table to use in Dapper.Contrib commands.
/// </summary>
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
public class TableAttribute : Attribute public class TableAttribute : Attribute
{ {
/// <summary>
/// Creates a table mapping to a specific name for Dapper.Contrib commands
/// </summary>
/// <param name="tableName">The name of this table in the database.</param>
public TableAttribute(string tableName) public TableAttribute(string tableName)
{ {
Name = tableName; Name = tableName;
} }
// ReSharper disable once MemberCanBePrivate.Global /// <summary>
// ReSharper disable once UnusedAutoPropertyAccessor.Global /// The name of the table in the database
/// </summary>
public string Name { get; set; } public string Name { get; set; }
} }
// do not want to depend on data annotations that is not in client profile /// <summary>
/// Specifies that this field is a primary key in the database
/// </summary>
[AttributeUsage(AttributeTargets.Property)] [AttributeUsage(AttributeTargets.Property)]
public class KeyAttribute : Attribute public class KeyAttribute : Attribute
{ {
} }
/// <summary>
/// Specifies that this field is a explicitly set primary key in the database
/// </summary>
[AttributeUsage(AttributeTargets.Property)] [AttributeUsage(AttributeTargets.Property)]
public class ExplicitKeyAttribute : Attribute public class ExplicitKeyAttribute : Attribute
{ {
} }
/// <summary>
/// Specifies whether a field is writable in the database.
/// </summary>
[AttributeUsage(AttributeTargets.Property)] [AttributeUsage(AttributeTargets.Property)]
public class WriteAttribute : Attribute public class WriteAttribute : Attribute
{ {
/// <summary>
/// Specifies whether a field is writable in the database.
/// </summary>
/// <param name="write">Whether a field is writable in the database.</param>
public WriteAttribute(bool write) public WriteAttribute(bool write)
{ {
Write = write; Write = write;
} }
/// <summary>
/// Whether a field is writable in the database.
/// </summary>
public bool Write { get; } public bool Write { get; }
} }
/// <summary>
/// Specifies that this is a computed column.
/// </summary>
[AttributeUsage(AttributeTargets.Property)] [AttributeUsage(AttributeTargets.Property)]
public class ComputedAttribute : Attribute public class ComputedAttribute : Attribute
{ {
} }
} }
/// <summary>
/// The interface for all Dapper.Contrib database operations
/// Implementing this is each provider's model.
/// </summary>
public partial interface ISqlAdapter public partial interface ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert); int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert);
//new methods for issue #336 /// <summary>
/// Adds the name of a column.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
void AppendColumnName(StringBuilder sb, string columnName); void AppendColumnName(StringBuilder sb, string columnName);
/// <summary>
/// Adds a column equality to a parameter.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
void AppendColumnNameEqualsValue(StringBuilder sb, string columnName); void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
} }
/// <summary>
/// The SQL Server database adapter.
/// </summary>
public partial class SqlServerAdapter : ISqlAdapter public partial class SqlServerAdapter : ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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 = $"insert into {tableName} ({columnList}) values ({parameterList});select SCOPE_IDENTITY() id"; var cmd = $"insert into {tableName} ({columnList}) values ({parameterList});select SCOPE_IDENTITY() id";
...@@ -716,19 +807,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com ...@@ -716,19 +807,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
return id; return id;
} }
/// <summary>
/// Adds the name of a column.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnName(StringBuilder sb, string columnName) public void AppendColumnName(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("[{0}]", columnName); sb.AppendFormat("[{0}]", columnName);
} }
/// <summary>
/// Adds a column equality to a parameter.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("[{0}] = @{1}", columnName, columnName); sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
} }
} }
/// <summary>
/// The SQL Server Compact Edition database adapter.
/// </summary>
public partial class SqlCeServerAdapter : ISqlAdapter public partial class SqlCeServerAdapter : ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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 = $"insert into {tableName} ({columnList}) values ({parameterList})"; var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
...@@ -747,19 +863,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com ...@@ -747,19 +863,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
return id; return id;
} }
/// <summary>
/// Adds the name of a column.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnName(StringBuilder sb, string columnName) public void AppendColumnName(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("[{0}]", columnName); sb.AppendFormat("[{0}]", columnName);
} }
/// <summary>
/// Adds a column equality to a parameter.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("[{0}] = @{1}", columnName, columnName); sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
} }
} }
/// <summary>
/// The MySQL database adapter.
/// </summary>
public partial class MySqlAdapter : ISqlAdapter public partial class MySqlAdapter : ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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 = $"insert into {tableName} ({columnList}) values ({parameterList})"; var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
...@@ -777,20 +918,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com ...@@ -777,20 +918,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
return Convert.ToInt32(id); return Convert.ToInt32(id);
} }
/// <summary>
/// Adds the name of a column.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnName(StringBuilder sb, string columnName) public void AppendColumnName(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("`{0}`", columnName); sb.AppendFormat("`{0}`", columnName);
} }
/// <summary>
/// Adds a column equality to a parameter.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("`{0}` = @{1}", columnName, columnName); sb.AppendFormat("`{0}` = @{1}", columnName, columnName);
} }
} }
/// <summary>
/// The Postgres database adapter.
/// </summary>
public partial class PostgresAdapter : ISqlAdapter public partial class PostgresAdapter : ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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 sb = new StringBuilder(); var sb = new StringBuilder();
...@@ -827,19 +992,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com ...@@ -827,19 +992,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
return id; return id;
} }
/// <summary>
/// Adds the name of a column.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnName(StringBuilder sb, string columnName) public void AppendColumnName(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("\"{0}\"", columnName); sb.AppendFormat("\"{0}\"", columnName);
} }
/// <summary>
/// Adds a column equality to a parameter.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName); sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
} }
} }
/// <summary>
/// The SQLite database adapter.
/// </summary>
public partial class SQLiteAdapter : ISqlAdapter public partial class SQLiteAdapter : ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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 = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id"; var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id";
...@@ -855,19 +1045,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com ...@@ -855,19 +1045,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
return id; return id;
} }
/// <summary>
/// Adds the name of a column.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnName(StringBuilder sb, string columnName) public void AppendColumnName(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("\"{0}\"", columnName); sb.AppendFormat("\"{0}\"", columnName);
} }
/// <summary>
/// Adds a column equality to a parameter.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName); sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
} }
} }
/// <summary>
/// The Firebase SQL adapeter.
/// </summary>
public partial class FbAdapter : ISqlAdapter public partial class FbAdapter : ISqlAdapter
{ {
/// <summary>
/// Inserts <paramref name="entityToInsert"/> into the database, returning the Id of the row created.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="transaction">The transaction to use.</param>
/// <param name="commandTimeout">The command timeout to use.</param>
/// <param name="tableName">The table to insert into.</param>
/// <param name="columnList">The columns to set with this insert.</param>
/// <param name="parameterList">The parameters to set for this insert.</param>
/// <param name="keyProperties">The key columns in this table.</param>
/// <param name="entityToInsert">The entity to insert.</param>
/// <returns>The Id of the row created.</returns>
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 = $"insert into {tableName} ({columnList}) values ({parameterList})"; var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
...@@ -887,11 +1102,21 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com ...@@ -887,11 +1102,21 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
return Convert.ToInt32(id); return Convert.ToInt32(id);
} }
/// <summary>
/// Adds the name of a column.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnName(StringBuilder sb, string columnName) public void AppendColumnName(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("{0}", columnName); sb.AppendFormat("{0}", columnName);
} }
/// <summary>
/// Adds a column equality to a parameter.
/// </summary>
/// <param name="sb">The string builder to append to.</param>
/// <param name="columnName">The column name.</param>
public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName) public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
{ {
sb.AppendFormat("{0} = @{1}", columnName, columnName); sb.AppendFormat("{0} = @{1}", columnName, columnName);
......
...@@ -45,7 +45,7 @@ public Task<int> UpdateAsync(TId id, dynamic data) ...@@ -45,7 +45,7 @@ public Task<int> UpdateAsync(TId id, dynamic data)
builder.AppendLine(string.Join(",", paramNames.Where(n => n != "Id").Select(p => p + "= @" + p))); builder.AppendLine(string.Join(",", paramNames.Where(n => n != "Id").Select(p => p + "= @" + p)));
builder.Append("where Id = @Id"); builder.Append("where Id = @Id");
DynamicParameters parameters = new DynamicParameters(data); var parameters = new DynamicParameters(data);
parameters.Add("Id", id); parameters.Add("Id", id);
return database.ExecuteAsync(builder.ToString(), parameters); return database.ExecuteAsync(builder.ToString(), parameters);
...@@ -62,61 +62,115 @@ public async Task<bool> DeleteAsync(TId id) ...@@ -62,61 +62,115 @@ public async Task<bool> DeleteAsync(TId id)
} }
/// <summary> /// <summary>
/// Grab a record with a particular Id from the DB asynchronously /// Asynchronously gets a record with a particular Id from the DB
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id">The primary key of the table to fetch.</param>
/// <returns></returns> /// <returns>The record with the specified Id.</returns>
public async Task<T> GetAsync(TId id) public Task<T> GetAsync(TId id)
{ {
return (await database.QueryAsync<T>("select * from " + TableName + " where Id = @id", new { id }).ConfigureAwait(false)).FirstOrDefault(); return database.QueryFirstOrDefaultAsync<T>("select * from " + TableName + " where Id = @id", new { id });
} }
public virtual async Task<T> FirstAsync() /// <summary>
/// Asynchronously gets the first row from this table (order determined by the database provider).
/// </summary>
/// <returns>Data from the first table row.</returns>
public virtual Task<T> FirstAsync()
{ {
return (await database.QueryAsync<T>("select top 1 * from " + TableName).ConfigureAwait(false)).FirstOrDefault(); return database.QueryFirstOrDefaultAsync<T>("select top 1 * from " + TableName);
} }
/// <summary>
/// Asynchronously gets the all rows from this table.
/// </summary>
/// <returns>Data from all table rows.</returns>
public Task<IEnumerable<T>> AllAsync() public Task<IEnumerable<T>> AllAsync()
{ {
return database.QueryAsync<T>("select * from " + TableName); return database.QueryAsync<T>("select * from " + TableName);
} }
} }
/// <summary>
/// Asynchronously executes SQL against the current database.
/// </summary>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <returns>The number of rows affected.</returns>
public Task<int> ExecuteAsync(string sql, dynamic param = null) public Task<int> ExecuteAsync(string sql, dynamic param = null)
{ {
return _connection.ExecuteAsync(sql, param as object, _transaction, this._commandTimeout); return _connection.ExecuteAsync(sql, param as object, _transaction, this._commandTimeout);
} }
/// <summary>
/// Asynchronously queries the current database.
/// </summary>
/// <typeparam name="T">The type to return.</typeparam>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns>
public Task<IEnumerable<T>> QueryAsync<T>(string sql, dynamic param = null) public Task<IEnumerable<T>> QueryAsync<T>(string sql, dynamic param = null)
{ {
return _connection.QueryAsync<T>(sql, param as object, _transaction, _commandTimeout); return _connection.QueryAsync<T>(sql, param as object, _transaction, _commandTimeout);
} }
/// <summary>
/// Asynchronously queries the current database for a single record.
/// </summary>
/// <typeparam name="T">The type to return.</typeparam>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns>
public Task<T> QueryFirstOrDefaultAsync<T>(string sql, dynamic param = null)
{
return _connection.QueryFirstOrDefaultAsync<T>(sql, param as object, _transaction, _commandTimeout);
}
/// <summary>
/// Perform an asynchronous multi mapping query with 2 input parameters
/// </summary>
public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn); return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Perform an asynchronous multi mapping query with 3 input parameters
/// </summary>
public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn); return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Perform an asynchronous multi mapping query with 4 input parameters
/// </summary>
public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn); return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Perform an asynchronous multi mapping query with 5 input parameters
/// </summary>
public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn); return _connection.QueryAsync(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Execute a query asynchronously using .NET 4.5 Task.
/// </summary>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <remarks>Note: each row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public Task<IEnumerable<dynamic>> QueryAsync(string sql, dynamic param = null) public Task<IEnumerable<dynamic>> QueryAsync(string sql, dynamic param = null)
{ {
return _connection.QueryAsync(sql, param as object, _transaction); return _connection.QueryAsync(sql, param as object, _transaction);
} }
/// <summary>
/// Execute a command that returns multiple result sets, and access each in turn
/// </summary>
public Task<SqlMapper.GridReader> QueryMultipleAsync(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) public Task<SqlMapper.GridReader> QueryMultipleAsync(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
{ {
return SqlMapper.QueryMultipleAsync(_connection, sql, param, transaction, commandTimeout, commandType); return SqlMapper.QueryMultipleAsync(_connection, sql, param, transaction, commandTimeout, commandType);
......
...@@ -11,23 +11,36 @@ ...@@ -11,23 +11,36 @@
namespace Dapper namespace Dapper
{ {
/// <summary> /// <summary>
/// A container for a database, assumes all the tables have an Id column named Id /// Represents a database, assumes all the tables have an Id column named Id
/// </summary> /// </summary>
/// <typeparam name="TDatabase"></typeparam> /// <typeparam name="TDatabase">The type of database this represents.</typeparam>
public abstract partial class Database<TDatabase> : IDisposable where TDatabase : Database<TDatabase>, new() public abstract partial class Database<TDatabase> : IDisposable where TDatabase : Database<TDatabase>, new()
{ {
/// <summary>
/// A database table of type <typeparamref name="T"/> and primary key of type <typeparamref name="TId"/>.
/// </summary>
/// <typeparam name="T">The type of object in this table.</typeparam>
/// <typeparam name="TId">The type of the primary key for this table.</typeparam>
public partial class Table<T, TId> public partial class Table<T, TId>
{ {
internal Database<TDatabase> database; internal Database<TDatabase> database;
internal string tableName; internal string tableName;
internal string likelyTableName; internal string likelyTableName;
/// <summary>
/// Creates a table in the specified database with a given name.
/// </summary>
/// <param name="database">The database this table belongs in.</param>
/// <param name="likelyTableName">The name for this table.</param>
public Table(Database<TDatabase> database, string likelyTableName) public Table(Database<TDatabase> database, string likelyTableName)
{ {
this.database = database; this.database = database;
this.likelyTableName = likelyTableName; this.likelyTableName = likelyTableName;
} }
/// <summary>
/// The name for this table.
/// </summary>
public string TableName public string TableName
{ {
get get
...@@ -56,11 +69,11 @@ public string TableName ...@@ -56,11 +69,11 @@ public string TableName
} }
/// <summary> /// <summary>
/// Update a record in the DB /// Update a record in the database.
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id">The primary key of the row to update.</param>
/// <param name="data"></param> /// <param name="data">The new object data.</param>
/// <returns></returns> /// <returns>The number of rows affected.</returns>
public int Update(TId id, dynamic data) public int Update(TId id, dynamic data)
{ {
List<string> paramNames = GetParamNames((object)data); List<string> paramNames = GetParamNames((object)data);
...@@ -87,26 +100,34 @@ public bool Delete(TId id) ...@@ -87,26 +100,34 @@ public bool Delete(TId id)
} }
/// <summary> /// <summary>
/// Grab a record with a particular Id from the DB /// Gets a record with a particular Id from the DB
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id">The primary key of the table to fetch.</param>
/// <returns></returns> /// <returns>The record with the specified Id.</returns>
public T Get(TId id) public T Get(TId id)
{ {
return database.Query<T>("select * from " + TableName + " where Id = @id", new { id }).FirstOrDefault(); return database.QueryFirstOrDefault<T>("select * from " + TableName + " where Id = @id", new { id });
} }
/// <summary>
/// Gets the first row from this table (order determined by the database provider).
/// </summary>
/// <returns>Data from the first table row.</returns>
public virtual T First() public virtual T First()
{ {
return database.Query<T>("select top 1 * from " + TableName).FirstOrDefault(); return database.QueryFirstOrDefault<T>("select top 1 * from " + TableName);
} }
/// <summary>
/// Gets the all rows from this table.
/// </summary>
/// <returns>Data from all table rows.</returns>
public IEnumerable<T> All() public IEnumerable<T> All()
{ {
return database.Query<T>("select * from " + TableName); return database.Query<T>("select * from " + TableName);
} }
private static ConcurrentDictionary<Type, List<string>> paramNameCache = new ConcurrentDictionary<Type, List<string>>(); private static readonly ConcurrentDictionary<Type, List<string>> paramNameCache = new ConcurrentDictionary<Type, List<string>>();
internal static List<string> GetParamNames(object o) internal static List<string> GetParamNames(object o)
{ {
...@@ -135,7 +156,17 @@ internal static List<string> GetParamNames(object o) ...@@ -135,7 +156,17 @@ internal static List<string> GetParamNames(object o)
} }
} }
public class Table<T> : Table<T, int> { /// <summary>
/// A database table of type <typeparamref name="T"/> and primary key of type <see cref="int"/>.
/// </summary>
/// <typeparam name="T">The type of object in this table.</typeparam>
public class Table<T> : Table<T, int>
{
/// <summary>
/// Creates a table in the specified database with a given name.
/// </summary>
/// <param name="database">The database this table belongs in.</param>
/// <param name="likelyTableName">The name for this table.</param>
public Table(Database<TDatabase> database, string likelyTableName) public Table(Database<TDatabase> database, string likelyTableName)
: base(database, likelyTableName) : base(database, likelyTableName)
{ {
...@@ -146,6 +177,12 @@ public Table(Database<TDatabase> database, string likelyTableName) ...@@ -146,6 +177,12 @@ public Table(Database<TDatabase> database, string likelyTableName)
private int _commandTimeout; private int _commandTimeout;
private DbTransaction _transaction; private DbTransaction _transaction;
/// <summary>
/// Initializes the database.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <param name="commandTimeout">The timeout to use (in seconds).</param>
/// <returns></returns>
public static TDatabase Init(DbConnection connection, int commandTimeout) public static TDatabase Init(DbConnection connection, int commandTimeout)
{ {
TDatabase db = new TDatabase(); TDatabase db = new TDatabase();
...@@ -172,28 +209,48 @@ internal virtual Action<TDatabase> CreateTableConstructorForTable() ...@@ -172,28 +209,48 @@ internal virtual Action<TDatabase> CreateTableConstructorForTable()
return CreateTableConstructor(typeof(Table<>), typeof(Table<,>)); return CreateTableConstructor(typeof(Table<>), typeof(Table<,>));
} }
/// <summary>
/// Begins a transaction in this database.
/// </summary>
/// <param name="isolation">The isolation level to use.</param>
public void BeginTransaction(IsolationLevel isolation = IsolationLevel.ReadCommitted) public void BeginTransaction(IsolationLevel isolation = IsolationLevel.ReadCommitted)
{ {
_transaction = _connection.BeginTransaction(isolation); _transaction = _connection.BeginTransaction(isolation);
} }
/// <summary>
/// Commits the current transaction in this database.
/// </summary>
public void CommitTransaction() public void CommitTransaction()
{ {
_transaction.Commit(); _transaction.Commit();
_transaction = null; _transaction = null;
} }
/// <summary>
/// Rolls back the current transaction in this database.
/// </summary>
public void RollbackTransaction() public void RollbackTransaction()
{ {
_transaction.Rollback(); _transaction.Rollback();
_transaction = null; _transaction = null;
} }
/// <summary>
/// Gets a table creation function for the specified type.
/// </summary>
/// <param name="tableType">The object type to create a table for.</param>
/// <returns>The function to create the <paramref name="tableType"/> table.</returns>
protected Action<TDatabase> CreateTableConstructor(Type tableType) protected Action<TDatabase> CreateTableConstructor(Type tableType)
{ {
return CreateTableConstructor(new[] {tableType}); return CreateTableConstructor(new[] {tableType});
} }
/// <summary>
/// Gets a table creation function for the specified types.
/// </summary>
/// <param name="tableTypes">The object types to create a table for.</param>
/// <returns>The function to create the <paramref name="tableTypes"/> tables.</returns>
protected Action<TDatabase> CreateTableConstructor(params Type[] tableTypes) protected Action<TDatabase> CreateTableConstructor(params Type[] tableTypes)
{ {
var dm = new DynamicMethod("ConstructInstances", null, new[] { typeof(TDatabase) }, true); var dm = new DynamicMethod("ConstructInstances", null, new[] { typeof(TDatabase) }, true);
...@@ -282,47 +339,97 @@ private bool TableExists(string name) ...@@ -282,47 +339,97 @@ private bool TableExists(string name)
return _connection.Query(builder.ToString(), new { schemaName, name }, _transaction).Count() == 1; return _connection.Query(builder.ToString(), new { schemaName, name }, _transaction).Count() == 1;
} }
/// <summary>
/// Executes SQL against the current database.
/// </summary>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <returns>The number of rows affected.</returns>
public int Execute(string sql, dynamic param = null) public int Execute(string sql, dynamic param = null)
{ {
return _connection.Execute(sql, param as object, _transaction, _commandTimeout); return _connection.Execute(sql, param as object, _transaction, _commandTimeout);
} }
/// <summary>
/// Queries the current database.
/// </summary>
/// <typeparam name="T">The type to return.</typeparam>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <param name="buffered">Whether to buffer the results.</param>
/// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns>
public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered = true) public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered = true)
{ {
return _connection.Query<T>(sql, param as object, _transaction, buffered, _commandTimeout); return _connection.Query<T>(sql, param as object, _transaction, buffered, _commandTimeout);
} }
/// <summary>
/// Queries the current database for a single record.
/// </summary>
/// <typeparam name="T">The type to return.</typeparam>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns>
public T QueryFirstOrDefault<T>(string sql, dynamic param = null)
{
return _connection.QueryFirstOrDefault<T>(sql, param as object, _transaction, _commandTimeout);
}
/// <summary>
/// Perform a multi mapping query with 2 input parameters
/// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn); return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Perform a multi mapping query with 3 input parameters
/// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn); return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Perform a multi mapping query with 4 input parameters
/// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn); return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Perform a multi mapping query with 5 input parameters
/// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null)
{ {
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn); return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
} }
/// <summary>
/// Return a sequence of dynamic objects with properties matching the columns
/// </summary>
/// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param>
/// <param name="buffered">Whether the results should be buffered in memory.</param>
/// <remarks>Note: each row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public IEnumerable<dynamic> Query(string sql, dynamic param = null, bool buffered = true) public IEnumerable<dynamic> Query(string sql, dynamic param = null, bool buffered = true)
{ {
return _connection.Query(sql, param as object, _transaction, buffered); return _connection.Query(sql, param as object, _transaction, buffered);
} }
/// <summary>
/// Execute a command that returns multiple result sets, and access each in turn
/// </summary>
public SqlMapper.GridReader QueryMultiple(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) public SqlMapper.GridReader QueryMultiple(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
{ {
return SqlMapper.QueryMultiple(_connection, sql, param, transaction, commandTimeout, commandType); return SqlMapper.QueryMultiple(_connection, sql, param, transaction, commandTimeout, commandType);
} }
/// <summary>
/// Disposes the current database, rolling back current transactions.
/// </summary>
public void Dispose() public void Dispose()
{ {
if (_connection.State != ConnectionState.Closed) if (_connection.State != ConnectionState.Closed)
......
...@@ -2,14 +2,24 @@ ...@@ -2,14 +2,24 @@
namespace Dapper namespace Dapper
{ {
/// <summary>
/// Specifies whether a property should be ignored for database operations.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class IgnorePropertyAttribute : Attribute public class IgnorePropertyAttribute : Attribute
{ {
/// <summary>
/// Specifies whether a property should be ignored for database operations.
/// </summary>
/// <param name="ignore">Whether to ignore this property.</param>
public IgnorePropertyAttribute(bool ignore) public IgnorePropertyAttribute(bool ignore)
{ {
Value = ignore; Value = ignore;
} }
/// <summary>
/// Whether to ignore this property.
/// </summary>
public bool Value { get; set; } public bool Value { get; set; }
} }
} }
...@@ -6,32 +6,62 @@ ...@@ -6,32 +6,62 @@
namespace Dapper namespace Dapper
{ {
/// <summary>
/// Snapshots an object for comparison later.
/// </summary>
public static class Snapshotter public static class Snapshotter
{ {
/// <summary>
/// Starts the snapshot of an objec by making a copy of the current state.
/// </summary>
/// <typeparam name="T">The type of object to snapshot.</typeparam>
/// <param name="obj">The object to snapshot.</param>
/// <returns>The snapshot of the object.</returns>
public static Snapshot<T> Start<T>(T obj) public static Snapshot<T> Start<T>(T obj)
{ {
return new Snapshot<T>(obj); return new Snapshot<T>(obj);
} }
/// <summary>
/// A snapshot of an object's state.
/// </summary>
/// <typeparam name="T"></typeparam>
public class Snapshot<T> public class Snapshot<T>
{ {
static Func<T, T> cloner; private static Func<T, T> cloner;
static Func<T, T, List<Change>> differ; private static Func<T, T, List<Change>> differ;
T memberWiseClone; private readonly T memberWiseClone;
T trackedObject; private readonly T trackedObject;
/// <summary>
/// Creates a snapshot from an object.
/// </summary>
/// <param name="original">The original object to snapshot.</param>
public Snapshot(T original) public Snapshot(T original)
{ {
memberWiseClone = Clone(original); memberWiseClone = Clone(original);
trackedObject = original; trackedObject = original;
} }
/// <summary>
/// A holder for listing new values of changes fields and properties.
/// </summary>
public class Change public class Change
{ {
/// <summary>
/// The name of the field or property that changed.
/// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// The new value of the field or property.
/// </summary>
public object NewValue { get; set; } public object NewValue { get; set; }
} }
/// <summary>
/// Does a diff between the original object and the current state.
/// </summary>
/// <returns>The list of the fields changes in the object.</returns>
public DynamicParameters Diff() public DynamicParameters Diff()
{ {
return Diff(memberWiseClone, trackedObject); return Diff(memberWiseClone, trackedObject);
...@@ -65,16 +95,13 @@ static List<PropertyInfo> RelevantProperties() ...@@ -65,16 +95,13 @@ static List<PropertyInfo> RelevantProperties()
(p.PropertyType.IsGenericType() && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))) (p.PropertyType.IsGenericType() && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
).ToList(); ).ToList();
} }
// This is used by IL, ReSharper is wrong.
// ReSharper disable UnusedMember.Local
private static bool AreEqual<U>(U first, U second) private static bool AreEqual<U>(U first, U second)
{ {
if (first == null && second == null) return true; if (EqualityComparer<U>.Default.Equals(first, default(U)) && EqualityComparer<U>.Default.Equals(second, default(U))) return true;
if (first == null) return false; if (EqualityComparer<U>.Default.Equals(first, default(U))) return false;
return first.Equals(second); return first.Equals(second);
} }
// ReSharper restore UnusedMember.Local
private static Func<T, T, List<Change>> GenerateDiffer() private static Func<T, T, List<Change>> GenerateDiffer()
{ {
...@@ -114,7 +141,7 @@ private static bool AreEqual<U>(U first, U second) ...@@ -114,7 +141,7 @@ private static bool AreEqual<U>(U first, U second)
il.Emit(OpCodes.Stloc_2); il.Emit(OpCodes.Stloc_2);
// [original prop val, current prop val] // [original prop val, current prop val]
il.EmitCall(OpCodes.Call, typeof(Snapshot<T>).GetMethod("AreEqual", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(new Type[] { prop.PropertyType }), null); il.EmitCall(OpCodes.Call, typeof(Snapshot<T>).GetMethod(nameof(AreEqual), BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(new Type[] { prop.PropertyType }), null);
// [result] // [result]
Label skip = il.DefineLabel(); Label skip = il.DefineLabel();
......
...@@ -5,10 +5,23 @@ ...@@ -5,10 +5,23 @@
namespace Dapper namespace Dapper
{ {
/// <summary>
/// A SQL Compact specific <see cref="Database{TDatabase}"/> implementation.
/// </summary>
/// <typeparam name="TDatabase">The type of database.</typeparam>
public abstract class SqlCompactDatabase<TDatabase> : Database<TDatabase> where TDatabase : Database<TDatabase>, new() public abstract class SqlCompactDatabase<TDatabase> : Database<TDatabase> where TDatabase : Database<TDatabase>, new()
{ {
/// <summary>
/// A SQL Compact specific table, which handles the syntax correctly across operations.
/// </summary>
/// <typeparam name="T">The type in the table.</typeparam>
public class SqlCompactTable<T> : Table<T> public class SqlCompactTable<T> : Table<T>
{ {
/// <summary>
/// Creates a table for a SQL Compact database.
/// </summary>
/// <param name="database"></param>
/// <param name="likelyTableName"></param>
public SqlCompactTable(Database<TDatabase> database, string likelyTableName) public SqlCompactTable(Database<TDatabase> database, string likelyTableName)
: base(database, likelyTableName) : base(database, likelyTableName)
{ {
...@@ -38,12 +51,17 @@ public SqlCompactTable(Database<TDatabase> database, string likelyTableName) ...@@ -38,12 +51,17 @@ public SqlCompactTable(Database<TDatabase> database, string likelyTableName)
} }
} }
/// <summary>
/// Initializes the databases.
/// </summary>
/// <param name="connection">The connection to use.</param>
/// <returns>The newly created database.</returns>
public static TDatabase Init(DbConnection connection) public static TDatabase Init(DbConnection connection)
{ {
TDatabase db = new TDatabase(); var db = new TDatabase();
db.InitDatabase(connection, 0); db.InitDatabase(connection, 0);
return db; return db;
} }
internal override Action<TDatabase> CreateTableConstructorForTable() internal override Action<TDatabase> CreateTableConstructorForTable()
{ {
......
...@@ -1112,7 +1112,7 @@ public PocoData(Type t) ...@@ -1112,7 +1112,7 @@ public PocoData(Type t)
{ {
var colattr = (Column)ColAttrs[0]; var colattr = (Column)ColAttrs[0];
pc.ColumnName = colattr.Name; pc.ColumnName = colattr.Name;
if ((colattr as ResultColumn) != null) if (colattr is ResultColumn)
pc.ResultColumn = true; pc.ResultColumn = true;
} }
if (pc.ColumnName == null) if (pc.ColumnName == null)
......
...@@ -24,12 +24,12 @@ public partial class DynamicParameters : SqlMapper.IDynamicParameters, SqlMapper ...@@ -24,12 +24,12 @@ public partial class DynamicParameters : SqlMapper.IDynamicParameters, SqlMapper
Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>(); Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>();
List<object> templates; List<object> templates;
object SqlMapper.IParameterLookup.this[string member] object SqlMapper.IParameterLookup.this[string name]
{ {
get get
{ {
ParamInfo param; ParamInfo param;
return parameters.TryGetValue(member, out param) ? param.Value : null; return parameters.TryGetValue(name, out param) ? param.Value : null;
} }
} }
......
...@@ -39,9 +39,9 @@ private sealed class DeadValue ...@@ -39,9 +39,9 @@ private sealed class DeadValue
} }
} }
public bool TryGetValue(string name, out object value) public bool TryGetValue(string key, out object value)
{ {
var index = table.IndexOfName(name); var index = table.IndexOfName(key);
if (index < 0) if (index < 0)
{ // doesn't exist { // doesn't exist
value = null; value = null;
......
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