diff --git a/Dapper/Dapper.csproj b/Dapper/Dapper.csproj index d3825cbf..9843c7ee 100644 --- a/Dapper/Dapper.csproj +++ b/Dapper/Dapper.csproj @@ -22,6 +22,8 @@ DEBUG;TRACE prompt 4 + true + bin\Debug\Dapper.XML pdbonly diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 6880e5d4..36dcacdd 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -19,10 +19,21 @@ using System.Text.RegularExpressions; namespace Dapper { + /// + /// Dapper, a light weight object mapper for ADO.NET + /// public static partial class SqlMapper { + /// + /// Implement this interface to pass an arbitrary db specific set of parameters to Dapper + /// public interface IDynamicParameters { + /// + /// Add all the parameters needed to the command just before it executes + /// + /// The raw command prior to execution + /// Information about the query void AddParameters(IDbCommand command, Identity identity); } static Link> bindByNameCache; @@ -115,6 +126,9 @@ namespace Dapper public void RecordHit() { Interlocked.Increment(ref hitCount); } } + /// + /// Called if the query cache is purged via PurgeQueryCache + /// public static event EventHandler QueryCachePurged; private static void OnQueryCachePurged() { @@ -185,18 +199,29 @@ namespace Dapper return false; } + /// + /// Purge the query cache + /// public static void PurgeQueryCache() { _queryCache.Clear(); OnQueryCachePurged(); } + /// + /// Return a count of all the cached queries by dapper + /// + /// public static int GetCachedSQLCount() { return _queryCache.Count; } - + /// + /// Return a list of all the queries cached by dapper + /// + /// + /// public static IEnumerable> GetCachedSQL(int ignoreHitCountAbove = int.MaxValue) { var data = _queryCache.Select(pair => Tuple.Create(pair.Key.connectionString, pair.Key.sql, pair.Value.GetHitCount())); @@ -204,6 +229,10 @@ namespace Dapper return data; } + /// + /// Deep diagnostics only: find any hash collisions in the cache + /// + /// public static IEnumerable> GetHashCollissions() { var counts = new Dictionary(); @@ -291,6 +320,9 @@ namespace Dapper throw new NotSupportedException(string.Format("The member {0} of type {1} cannot be used as a parameter value", name, type)); } + /// + /// Identity of a cached query in Dapper, used for extensability + /// public class Identity : IEquatable { internal Identity ForGrid(Type primaryType, int gridIndex) @@ -302,7 +334,11 @@ namespace Dapper { return new Identity(sql, commandType, connectionString, primaryType, parametersType, otherTypes, gridIndex); } - + /// + /// Create an identity for use with DynamicParameters, internal use only + /// + /// + /// public Identity ForDynamicParameters(Type type) { return new Identity(sql, commandType, connectionString, this.type ,type, null, -1); @@ -337,20 +373,51 @@ namespace Dapper hashCode = hashCode * 23 + (parametersType == null ? 0 : parametersType.GetHashCode()); } } + + /// + /// + /// + /// + /// public override bool Equals(object obj) { return Equals(obj as Identity); } + /// + /// The sql + /// public readonly string sql; + /// + /// The command type + /// public readonly CommandType? commandType; + + /// + /// + /// public readonly int hashCode, gridIndex; private readonly Type type; + /// + /// + /// public readonly string connectionString; + /// + /// + /// public readonly Type parametersType; + /// + /// + /// + /// public override int GetHashCode() { return hashCode; } + /// + /// Compare 2 Identity objects + /// + /// + /// public bool Equals(Identity other) { return @@ -451,7 +518,7 @@ this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transac /// /// Executes a query, returning the data typed as per T /// - /// the dynamic param may seem a bit odd, but this works around a major usability issue in vs, if it is Object vs completion gets annoying. Eg type new get new object + /// the dynamic param may seem a bit odd, but this works around a major usability issue in vs, if it is Object vs completion gets annoying. Eg type new [space] get new object /// A sequence of data of the supplied type; if a basic type (int, string, etc) is queried then the data from the first column in assumed, otherwise an instance is /// created per row, and a direct column-name===member-name mapping is assumed (case insensitive). /// @@ -546,8 +613,9 @@ this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transac /// /// Maps a query to objects /// - /// The return type - /// + /// The first type in the recordset + /// The second type in the recordset + /// The return type /// /// /// @@ -556,6 +624,7 @@ this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transac /// /// The Field we should split and read the second object from (default: id) /// Number of seconds before command execution timeout + /// Is it a stored proc or a batch? /// public static IEnumerable Query( #if CSHARP30 @@ -568,6 +637,23 @@ this IDbConnection cnn, string sql, Func map, dynamic return MultiMap(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); } + /// + /// Maps a query to objects + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// The Field we should split and read the second object from (default: id) + /// Number of seconds before command execution timeout + /// + /// public static IEnumerable Query( #if CSHARP30 this IDbConnection cnn, string sql, Func map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType @@ -579,6 +665,24 @@ this IDbConnection cnn, string sql, Func map, return MultiMap(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); } + /// + /// Perform a multi mapping query with 4 input parameters + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public static IEnumerable Query( #if CSHARP30 this IDbConnection cnn, string sql, Func map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType @@ -590,6 +694,25 @@ this IDbConnection cnn, string sql, Func(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); } #if !CSHARP30 + /// + /// Perform a multi mapping query with 5 input parameters + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public static IEnumerable Query(this IDbConnection cnn, string sql, Func map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null) { return MultiMap(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); @@ -977,6 +1100,11 @@ this IDbConnection cnn, string sql, Func + /// Internal use only + /// + /// + /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("This method is for internal usage only", false)] public static char ReadChar(object value) @@ -986,6 +1114,10 @@ this IDbConnection cnn, string sql, Func + /// Internal use only + /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("This method is for internal usage only", false)] public static char? ReadNullableChar(object value) @@ -995,6 +1127,9 @@ this IDbConnection cnn, string sql, Func + /// Internal use only + /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("This method is for internal usage only", true)] public static void PackListParameters(IDbCommand command, string namePrefix, object value) @@ -1051,6 +1186,9 @@ this IDbConnection cnn, string sql, Func Regex.IsMatch(sql, "[@:]" + p.Name + "([^a-zA-Z0-9_]+|$)", RegexOptions.IgnoreCase | RegexOptions.Multiline)); } + /// + /// Internal use only + /// public static Action CreateParamInfoGenerator(Identity identity) { Type type = identity.parametersType; @@ -1290,6 +1428,15 @@ this IDbConnection cnn, string sql, Func + /// Internal use only + /// + /// + /// + /// + /// + /// + /// public static Func GetClassDeserializer( #if CSHARP30 Type type, IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing @@ -1475,6 +1622,13 @@ this IDbConnection cnn, string sql, Func)dm.CreateDelegate(typeof(Func)); } + + /// + /// Throws a data exception, only used internally + /// + /// + /// + /// public static void ThrowDataException(Exception ex, int index, IDataReader reader) { string name = "(n/a)", value = "(n/a)"; @@ -1520,6 +1674,9 @@ this IDbConnection cnn, string sql, Func + /// The grid reader provides interfaces for reading multiple result sets from a Dapper query + /// public class GridReader : IDisposable { private IDataReader reader; @@ -1581,6 +1738,15 @@ this IDbConnection cnn, string sql, Func + /// Read multiple objects from a single recordset on the grid + /// + /// + /// + /// + /// + /// + /// #if CSHARP30 public IEnumerable Read(Func func, string splitOn) #else @@ -1590,6 +1756,16 @@ this IDbConnection cnn, string sql, Func(func, splitOn); } + /// + /// Read multiple objects from a single recordset on the grid + /// + /// + /// + /// + /// + /// + /// + /// #if CSHARP30 public IEnumerable Read(Func func, string splitOn) #else @@ -1599,6 +1775,17 @@ this IDbConnection cnn, string sql, Func(func, splitOn); } + /// + /// Read multiple objects from a single record set on the grid + /// + /// + /// + /// + /// + /// + /// + /// + /// #if CSHARP30 public IEnumerable Read(Func func, string splitOn) #else @@ -1609,6 +1796,18 @@ this IDbConnection cnn, string sql, Func + /// Read multiple objects from a single record set on the grid + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public IEnumerable Read(Func func, string splitOn = "id") { @@ -1658,6 +1857,9 @@ this IDbConnection cnn, string sql, Func + /// Dispose the grid, closing and disposing both the underlying reader and command. + /// public void Dispose() { if (reader != null) @@ -1673,6 +1875,10 @@ this IDbConnection cnn, string sql, Func + /// A bag of parameters that can be passed to the Dapper Query and Execute methods + /// public class DynamicParameters : SqlMapper.IDynamicParameters { static Dictionary> paramReaderCache = new Dictionary>(); @@ -1690,7 +1896,14 @@ this IDbConnection cnn, string sql, Func + /// construct a dynamic parameter bag + /// public DynamicParameters() { } + /// + /// construct a dynamic parameter bag + /// + /// can be an anonymous type of a DynamicParameters bag public DynamicParameters(object template) { if (template != null) @@ -1744,7 +1957,14 @@ this IDbConnection cnn, string sql, Func + /// Add a parameter to this dynamic parameter list + /// + /// + /// + /// + /// + /// public void Add( #if CSHARP30 string name, object value, DbType? dbType, ParameterDirection? direction, int? size @@ -1821,6 +2041,12 @@ string name, object value = null, DbType? dbType = null, ParameterDirection? dir } } + /// + /// Get the value of a parameter + /// + /// + /// + /// The value, note DBNull.Value is not returned, instead the value is returned as null public T Get(string name) { var val = parameters[Clean(name)].AttachedParam.Value; @@ -1835,13 +2061,37 @@ string name, object value = null, DbType? dbType = null, ParameterDirection? dir return (T)val; } } + + /// + /// This class represents a SQL string, it can be used if you need to denote your parameter is a Char vs VarChar vs nVarChar vs nChar + /// public sealed class DbString { + /// + /// Create a new DbString + /// public DbString() { Length = -1; } + /// + /// Ansi vs Unicode + /// public bool IsAnsi { get; set; } + /// + /// Fixed length + /// public bool IsFixedLength { get; set; } + /// + /// Length of the string -1 for max + /// public int Length { get; set; } + /// + /// The value of the string + /// public string Value { get; set; } + /// + /// Add the parameter to the command... internal use only + /// + /// + /// public void AddParameter(IDbCommand command, string name) { if (IsFixedLength && Length == -1)