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
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);
}
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)
{
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
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)
{
var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList})";
......@@ -353,6 +389,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
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,
string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
......@@ -373,7 +421,19 @@ public partial class MySqlAdapter
}
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)
{
var sb = new StringBuilder();
......@@ -414,6 +474,18 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
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)
{
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
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)
{
var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
......
......@@ -17,20 +17,44 @@
namespace Dapper.Contrib.Extensions
{
/// <summary>
/// The Dapper.Contrib extensions for Dapper
/// </summary>
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
{
/// <summary>
/// Whether the object has been changed.
/// </summary>
bool IsDirty { get; set; }
}
/// <summary>
/// Defines a table name mapper for getting table names from types.
/// </summary>
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);
}
/// <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);
/// <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);
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
}
}
/// <summary>
/// Defines the name of a table to use in Dapper.Contrib commands.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
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)
{
Name = tableName;
}
// ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once UnusedAutoPropertyAccessor.Global
/// <summary>
/// The name of the table in the database
/// </summary>
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)]
public class KeyAttribute : Attribute
{
}
/// <summary>
/// Specifies that this field is a explicitly set primary key in the database
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ExplicitKeyAttribute : Attribute
{
}
/// <summary>
/// Specifies whether a field is writable in the database.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
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)
{
Write = write;
}
/// <summary>
/// Whether a field is writable in the database.
/// </summary>
public bool Write { get; }
}
/// <summary>
/// Specifies that this is a computed column.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
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
{
/// <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);
//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);
/// <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);
}
/// <summary>
/// The SQL Server database adapter.
/// </summary>
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)
{
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
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)
{
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)
{
sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
}
}
/// <summary>
/// The SQL Server Compact Edition database adapter.
/// </summary>
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)
{
var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
......@@ -747,19 +863,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
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)
{
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)
{
sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
}
}
/// <summary>
/// The MySQL database adapter.
/// </summary>
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)
{
var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
......@@ -777,20 +918,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
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)
{
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)
{
sb.AppendFormat("`{0}` = @{1}", columnName, columnName);
}
}
/// <summary>
/// The Postgres database adapter.
/// </summary>
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)
{
var sb = new StringBuilder();
......@@ -827,19 +992,44 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
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)
{
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)
{
sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
}
}
/// <summary>
/// The SQLite database adapter.
/// </summary>
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)
{
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
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)
{
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)
{
sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
}
}
/// <summary>
/// The Firebase SQL adapeter.
/// </summary>
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)
{
var cmd = $"insert into {tableName} ({columnList}) values ({parameterList})";
......@@ -887,11 +1102,21 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
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)
{
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)
{
sb.AppendFormat("{0} = @{1}", columnName, columnName);
......
......@@ -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.Append("where Id = @Id");
DynamicParameters parameters = new DynamicParameters(data);
var parameters = new DynamicParameters(data);
parameters.Add("Id", id);
return database.ExecuteAsync(builder.ToString(), parameters);
......@@ -62,61 +62,115 @@ public async Task<bool> DeleteAsync(TId id)
}
/// <summary>
/// Grab a record with a particular Id from the DB asynchronously
/// Asynchronously gets a record with a particular Id from the DB
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<T> GetAsync(TId id)
/// <param name="id">The primary key of the table to fetch.</param>
/// <returns>The record with the specified Id.</returns>
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()
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
return SqlMapper.QueryMultipleAsync(_connection, sql, param, transaction, commandTimeout, commandType);
......
......@@ -11,23 +11,36 @@
namespace Dapper
{
/// <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>
/// <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()
{
/// <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>
{
internal Database<TDatabase> database;
internal string tableName;
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)
{
this.database = database;
this.likelyTableName = likelyTableName;
}
/// <summary>
/// The name for this table.
/// </summary>
public string TableName
{
get
......@@ -56,11 +69,11 @@ public string TableName
}
/// <summary>
/// Update a record in the DB
/// Update a record in the database.
/// </summary>
/// <param name="id"></param>
/// <param name="data"></param>
/// <returns></returns>
/// <param name="id">The primary key of the row to update.</param>
/// <param name="data">The new object data.</param>
/// <returns>The number of rows affected.</returns>
public int Update(TId id, dynamic data)
{
List<string> paramNames = GetParamNames((object)data);
......@@ -87,26 +100,34 @@ public bool Delete(TId id)
}
/// <summary>
/// Grab a record with a particular Id from the DB
/// Gets a record with a particular Id from the DB
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <param name="id">The primary key of the table to fetch.</param>
/// <returns>The record with the specified Id.</returns>
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()
{
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()
{
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)
{
......@@ -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)
: base(database, likelyTableName)
{
......@@ -146,6 +177,12 @@ public Table(Database<TDatabase> database, string likelyTableName)
private int _commandTimeout;
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)
{
TDatabase db = new TDatabase();
......@@ -172,28 +209,48 @@ internal virtual Action<TDatabase> CreateTableConstructorForTable()
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)
{
_transaction = _connection.BeginTransaction(isolation);
}
/// <summary>
/// Commits the current transaction in this database.
/// </summary>
public void CommitTransaction()
{
_transaction.Commit();
_transaction = null;
}
/// <summary>
/// Rolls back the current transaction in this database.
/// </summary>
public void RollbackTransaction()
{
_transaction.Rollback();
_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)
{
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)
{
var dm = new DynamicMethod("ConstructInstances", null, new[] { typeof(TDatabase) }, true);
......@@ -282,47 +339,97 @@ private bool TableExists(string name)
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
return SqlMapper.QueryMultiple(_connection, sql, param, transaction, commandTimeout, commandType);
}
/// <summary>
/// Disposes the current database, rolling back current transactions.
/// </summary>
public void Dispose()
{
if (_connection.State != ConnectionState.Closed)
......
......@@ -2,14 +2,24 @@
namespace Dapper
{
/// <summary>
/// Specifies whether a property should be ignored for database operations.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
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)
{
Value = ignore;
}
/// <summary>
/// Whether to ignore this property.
/// </summary>
public bool Value { get; set; }
}
}
......@@ -6,32 +6,62 @@
namespace Dapper
{
/// <summary>
/// Snapshots an object for comparison later.
/// </summary>
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)
{
return new Snapshot<T>(obj);
}
/// <summary>
/// A snapshot of an object's state.
/// </summary>
/// <typeparam name="T"></typeparam>
public class Snapshot<T>
{
static Func<T, T> cloner;
static Func<T, T, List<Change>> differ;
T memberWiseClone;
T trackedObject;
private static Func<T, T> cloner;
private static Func<T, T, List<Change>> differ;
private readonly T memberWiseClone;
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)
{
memberWiseClone = Clone(original);
trackedObject = original;
}
/// <summary>
/// A holder for listing new values of changes fields and properties.
/// </summary>
public class Change
{
/// <summary>
/// The name of the field or property that changed.
/// </summary>
public string Name { get; set; }
/// <summary>
/// The new value of the field or property.
/// </summary>
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()
{
return Diff(memberWiseClone, trackedObject);
......@@ -65,16 +95,13 @@ static List<PropertyInfo> RelevantProperties()
(p.PropertyType.IsGenericType() && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
).ToList();
}
// This is used by IL, ReSharper is wrong.
// ReSharper disable UnusedMember.Local
private static bool AreEqual<U>(U first, U second)
{
if (first == null && second == null) return true;
if (first == null) return false;
if (EqualityComparer<U>.Default.Equals(first, default(U)) && EqualityComparer<U>.Default.Equals(second, default(U))) return true;
if (EqualityComparer<U>.Default.Equals(first, default(U))) return false;
return first.Equals(second);
}
// ReSharper restore UnusedMember.Local
private static Func<T, T, List<Change>> GenerateDiffer()
{
......@@ -114,7 +141,7 @@ private static bool AreEqual<U>(U first, U second)
il.Emit(OpCodes.Stloc_2);
// [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]
Label skip = il.DefineLabel();
......
......@@ -5,10 +5,23 @@
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()
{
/// <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>
{
/// <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)
: base(database, 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)
{
TDatabase db = new TDatabase();
var db = new TDatabase();
db.InitDatabase(connection, 0);
return db;
}
}
internal override Action<TDatabase> CreateTableConstructorForTable()
{
......
......@@ -1112,7 +1112,7 @@ public PocoData(Type t)
{
var colattr = (Column)ColAttrs[0];
pc.ColumnName = colattr.Name;
if ((colattr as ResultColumn) != null)
if (colattr is ResultColumn)
pc.ResultColumn = true;
}
if (pc.ColumnName == null)
......
......@@ -24,12 +24,12 @@ public partial class DynamicParameters : SqlMapper.IDynamicParameters, SqlMapper
Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>();
List<object> templates;
object SqlMapper.IParameterLookup.this[string member]
object SqlMapper.IParameterLookup.this[string name]
{
get
{
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
}
}
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)
{ // doesn't exist
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