diff --git a/Dapper.sln b/Dapper.sln
index e993c7a4..4aa75f10 100644
--- a/Dapper.sln
+++ b/Dapper.sln
@@ -16,7 +16,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
version.json = version.json
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Contrib", "Dapper.Contrib\Dapper.Contrib.csproj", "{4E409F8F-CFBB-4332-8B0A-FD5A283051FD}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Contrib", "src\Dapper.Contrib\Dapper.Contrib.csproj", "{4E409F8F-CFBB-4332-8B0A-FD5A283051FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapper.Tests.Contrib", "tests\Dapper.Tests.Contrib\Dapper.Tests.Contrib.csproj", "{DAB3C5B7-BCD1-4A5F-BB6B-50D2BB63DB4A}"
EndProject
diff --git a/Readme.md b/Readme.md
index 9a1fd892..86e294a7 100644
--- a/Readme.md
+++ b/Readme.md
@@ -166,7 +166,19 @@ Dapper.Contrib makes use of some optional attributes:
```
* `[Write(true/false)]` - this property is (not) writeable
* `[Computed]` - this property is computed and should not be part of updates
-
+* `[Column("Columnname")]` - this property has a different name in the Database
+ * Property is called EmployeeId but Column in DB is called employee_id
+
+ ```csharp
+ public class Employee
+ {
+ [ExplicitKey]
+ [Column("employee_id")]
+ public Guid EmployeeId { get; set; }
+ public string Name { get; set; }
+ }
+ ```
+
Limitations and caveats
-------
diff --git a/src/Dapper.Contrib/PropertyInfoExtensions.cs b/src/Dapper.Contrib/PropertyInfoExtensions.cs
new file mode 100644
index 00000000..7d362640
--- /dev/null
+++ b/src/Dapper.Contrib/PropertyInfoExtensions.cs
@@ -0,0 +1,55 @@
+using System.Collections.Concurrent;
+using System.Linq;
+using System.Reflection;
+
+namespace Dapper.Contrib.Extensions
+{
+ ///
+ /// Map to database column extensions
+ ///
+ public static class PropertyInfoExtensions
+ {
+ private static readonly ConcurrentDictionary PropertyColumnName = new ConcurrentDictionary();
+
+ ///
+ /// The function to get a column name from a given
+ ///
+ /// The to get a column name for.
+ public delegate string ColumnNameMapperDelegate(PropertyInfo property);
+
+ ///
+ /// Specify a custom column name mapper based on the POCO type name
+ ///
+#pragma warning disable CA2211 // Non-constant fields should not be visible - I agree with you, but we can't do that until we break the API
+ public static ColumnNameMapperDelegate ColumnNameMapper;
+#pragma warning restore CA2211 // Non-constant fields should not be visible
+
+ ///
+ /// Get database column name from
+ ///
+ /// The to get a column name for.
+ public static string ColumnName(this PropertyInfo property)
+ {
+ if (PropertyColumnName.TryGetValue(property, out string name)) return name;
+
+ if (ColumnNameMapper != null)
+ {
+ name = ColumnNameMapper(property);
+ }
+ else
+ {
+ //NOTE: This as dynamic trick falls back to handle both our own Column-attribute as well as the one in EntityFramework
+ var columnAttrName =
+ property.GetCustomAttribute(true)?.Name
+ ?? (property.GetCustomAttributes(true).FirstOrDefault(attr => attr.GetType().Name == "ColumnAttribute") as dynamic)?.Name;
+
+ name = columnAttrName != null
+ ? columnAttrName
+ : property.Name;
+ }
+
+ PropertyColumnName[property] = name;
+ return name;
+ }
+ }
+}
diff --git a/src/Dapper.Contrib/SqlMapperExtensions.Async.cs b/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
index c93e39a4..f6335e03 100644
--- a/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
+++ b/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
@@ -25,13 +25,34 @@ public static partial class SqlMapperExtensions
public static async Task GetAsync(this IDbConnection connection, dynamic id, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
{
var type = typeof(T);
- if (!GetQueries.TryGetValue(type.TypeHandle, out string sql))
+ var properties = TypePropertiesCache(type);
+ var adapter = GetFormatter(connection);
+
+ var getQueriesKey = new GetQueriesCacheKey(type.TypeHandle, adapter.GetType().TypeHandle);
+
+ if (!GetQueries.TryGetValue(getQueriesKey, out string sql))
{
var key = GetSingleKey(nameof(GetAsync));
- var name = GetTableName(type);
+ var name = type.TableName();
+
+ StringBuilder sqlStringBuilder = new StringBuilder("select ");
+
+ foreach (PropertyInfo property in properties)
+ {
+ adapter.AppendColumnName(sqlStringBuilder, property.ColumnName());
+ sqlStringBuilder.Append(" as ");
+ adapter.AppendColumnName(sqlStringBuilder, property.Name);
+ sqlStringBuilder.AppendLine(",");
+ }
+
+ sqlStringBuilder.Remove(sqlStringBuilder.Length - 3, 2);
+
+ sqlStringBuilder.Append($" from {name} where ");
+ adapter.AppendColumnNameEqualsValue(sqlStringBuilder, key.ColumnName(), "id");
- sql = $"SELECT * FROM {name} WHERE {key.Name} = @id";
- GetQueries[type.TypeHandle] = sql;
+ sql = sqlStringBuilder.ToString();
+
+ GetQueries[getQueriesKey] = sql;
}
var dynParams = new DynamicParameters();
@@ -47,7 +68,7 @@ public static async Task GetAsync(this IDbConnection connection, dynamic i
var obj = ProxyGenerator.GetInterfaceProxy();
- foreach (var property in TypePropertiesCache(type))
+ foreach (var property in properties)
{
var val = res[property.Name];
if (val == null) continue;
@@ -82,14 +103,32 @@ public static Task> GetAllAsync(this IDbConnection connection,
{
var type = typeof(T);
var cacheType = typeof(List);
+ var properties = TypePropertiesCache(type);
+ var adapter = GetFormatter(connection);
- if (!GetQueries.TryGetValue(cacheType.TypeHandle, out string sql))
+ var getQueriesKey = new GetQueriesCacheKey(cacheType.TypeHandle, adapter.GetType().TypeHandle);
+
+ if (!GetQueries.TryGetValue(getQueriesKey, out string sql))
{
GetSingleKey(nameof(GetAll));
- var name = GetTableName(type);
+ var name = type.TableName();
+
+ StringBuilder sqlStringBuilder = new StringBuilder("select ");
+
+ foreach (PropertyInfo property in properties)
+ {
+ adapter.AppendColumnName(sqlStringBuilder, property.ColumnName());
+ sqlStringBuilder.Append(" as ");
+ adapter.AppendColumnName(sqlStringBuilder, property.Name);
+ sqlStringBuilder.AppendLine(",");
+ }
+
+ sqlStringBuilder.Remove(sqlStringBuilder.Length - 3, 2);
+
+ sqlStringBuilder.Append($" from {name} ");
- sql = "SELECT * FROM " + name;
- GetQueries[cacheType.TypeHandle] = sql;
+ sql = sqlStringBuilder.ToString();
+ GetQueries[getQueriesKey] = sql;
}
if (!type.IsInterface)
@@ -108,7 +147,7 @@ private static async Task> GetAllAsyncImpl(IDbConnection conne
var obj = ProxyGenerator.GetInterfaceProxy();
foreach (var property in TypePropertiesCache(type))
{
- var val = res[property.Name];
+ var val = res[property.ColumnName()];
if (val == null) continue;
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
@@ -162,7 +201,7 @@ public static Task InsertAsync(this IDbConnection connection, T entityTo
}
}
- var name = GetTableName(type);
+ var name = type.TableName();
var sbColumnList = new StringBuilder(null);
var allProperties = TypePropertiesCache(type);
var keyProperties = KeyPropertiesCache(type).ToList();
@@ -172,7 +211,7 @@ public static Task InsertAsync(this IDbConnection connection, T entityTo
for (var i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++)
{
var property = allPropertiesExceptKeyAndComputed[i];
- sqlAdapter.AppendColumnName(sbColumnList, property.Name);
+ sqlAdapter.AppendColumnName(sbColumnList, property.ColumnName());
if (i < allPropertiesExceptKeyAndComputed.Count - 1)
sbColumnList.Append(", ");
}
@@ -237,7 +276,7 @@ public static async Task UpdateAsync(this IDbConnection connection, T e
if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0)
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
- var name = GetTableName(type);
+ var name = type.TableName();
var sb = new StringBuilder();
sb.AppendFormat("update {0} set ", name);
@@ -252,7 +291,7 @@ public static async Task UpdateAsync(this IDbConnection connection, T e
for (var i = 0; i < nonIdProps.Count; i++)
{
var property = nonIdProps[i];
- adapter.AppendColumnNameEqualsValue(sb, property.Name);
+ adapter.AppendColumnNameEqualsValue(sb, property.ColumnName(), property.Name);
if (i < nonIdProps.Count - 1)
sb.Append(", ");
}
@@ -260,7 +299,7 @@ public static async Task UpdateAsync(this IDbConnection connection, T e
for (var i = 0; i < keyProperties.Count; i++)
{
var property = keyProperties[i];
- adapter.AppendColumnNameEqualsValue(sb, property.Name);
+ adapter.AppendColumnNameEqualsValue(sb, property.ColumnName(), property.Name);
if (i < keyProperties.Count - 1)
sb.Append(" and ");
}
@@ -306,7 +345,7 @@ public static async Task DeleteAsync(this IDbConnection connection, T e
if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0)
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
- var name = GetTableName(type);
+ var name = type.TableName();
var allKeyProperties = keyProperties.Concat(explicitKeyProperties).ToList();
var sb = new StringBuilder();
@@ -317,7 +356,7 @@ public static async Task DeleteAsync(this IDbConnection connection, T e
for (var i = 0; i < allKeyProperties.Count; i++)
{
var property = allKeyProperties[i];
- adapter.AppendColumnNameEqualsValue(sb, property.Name);
+ adapter.AppendColumnNameEqualsValue(sb, property.ColumnName(), property.Name);
if (i < allKeyProperties.Count - 1)
sb.Append(" AND ");
}
@@ -336,7 +375,7 @@ public static async Task DeleteAsync(this IDbConnection connection, T e
public static async Task DeleteAllAsync(this IDbConnection connection, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
{
var type = typeof(T);
- var statement = "DELETE FROM " + GetTableName(type);
+ var statement = "DELETE FROM " + type.TableName();
var deleted = await connection.ExecuteAsync(statement, null, transaction, commandTimeout).ConfigureAwait(false);
return deleted > 0;
}
diff --git a/src/Dapper.Contrib/SqlMapperExtensions.cs b/src/Dapper.Contrib/SqlMapperExtensions.cs
index 9a30e805..d2b91530 100644
--- a/src/Dapper.Contrib/SqlMapperExtensions.cs
+++ b/src/Dapper.Contrib/SqlMapperExtensions.cs
@@ -46,18 +46,12 @@ public interface ITableNameMapper
///
/// The connection to get a database type name from.
public delegate string GetDatabaseTypeDelegate(IDbConnection connection);
- ///
- /// The function to get a table name from a given
- ///
- /// The to get a table name for.
- public delegate string TableNameMapperDelegate(Type type);
- private static readonly ConcurrentDictionary> KeyProperties = new ConcurrentDictionary>();
- private static readonly ConcurrentDictionary> ExplicitKeyProperties = new ConcurrentDictionary>();
- private static readonly ConcurrentDictionary> TypeProperties = new ConcurrentDictionary>();
- private static readonly ConcurrentDictionary> ComputedProperties = new ConcurrentDictionary>();
- private static readonly ConcurrentDictionary GetQueries = new ConcurrentDictionary();
- private static readonly ConcurrentDictionary TypeTableName = new ConcurrentDictionary();
+ private static readonly ConcurrentDictionary> KeyProperties = new ConcurrentDictionary>();
+ private static readonly ConcurrentDictionary> ExplicitKeyProperties = new ConcurrentDictionary>();
+ private static readonly ConcurrentDictionary> TypeProperties = new ConcurrentDictionary>();
+ private static readonly ConcurrentDictionary> ComputedProperties = new ConcurrentDictionary>();
+ private static readonly ConcurrentDictionary GetQueries = new ConcurrentDictionary();
private static readonly ISqlAdapter DefaultAdapter = new SqlServerAdapter();
private static readonly Dictionary AdapterDictionary
@@ -73,9 +67,9 @@ private static readonly Dictionary AdapterDictionary
private static List ComputedPropertiesCache(Type type)
{
- if (ComputedProperties.TryGetValue(type.TypeHandle, out IEnumerable pi))
+ if (ComputedProperties.TryGetValue(type.TypeHandle, out List pi))
{
- return pi.ToList();
+ return pi;
}
var computedProperties = TypePropertiesCache(type).Where(p => p.GetCustomAttributes(true).Any(a => a is ComputedAttribute)).ToList();
@@ -86,9 +80,9 @@ private static List ComputedPropertiesCache(Type type)
private static List ExplicitKeyPropertiesCache(Type type)
{
- if (ExplicitKeyProperties.TryGetValue(type.TypeHandle, out IEnumerable pi))
+ if (ExplicitKeyProperties.TryGetValue(type.TypeHandle, out List pi))
{
- return pi.ToList();
+ return pi;
}
var explicitKeyProperties = TypePropertiesCache(type).Where(p => p.GetCustomAttributes(true).Any(a => a is ExplicitKeyAttribute)).ToList();
@@ -99,9 +93,9 @@ private static List ExplicitKeyPropertiesCache(Type type)
private static List KeyPropertiesCache(Type type)
{
- if (KeyProperties.TryGetValue(type.TypeHandle, out IEnumerable pi))
+ if (KeyProperties.TryGetValue(type.TypeHandle, out List pi))
{
- return pi.ToList();
+ return pi;
}
var allProperties = TypePropertiesCache(type);
@@ -109,7 +103,7 @@ private static List KeyPropertiesCache(Type type)
if (keyProperties.Count == 0)
{
- var idProp = allProperties.Find(p => string.Equals(p.Name, "id", StringComparison.CurrentCultureIgnoreCase));
+ var idProp = allProperties.Find(p => string.Equals(p.ColumnName(), "id", StringComparison.CurrentCultureIgnoreCase));
if (idProp != null && !idProp.GetCustomAttributes(true).Any(a => a is ExplicitKeyAttribute))
{
keyProperties.Add(idProp);
@@ -122,12 +116,12 @@ private static List KeyPropertiesCache(Type type)
private static List TypePropertiesCache(Type type)
{
- if (TypeProperties.TryGetValue(type.TypeHandle, out IEnumerable pis))
+ if (TypeProperties.TryGetValue(type.TypeHandle, out List pis))
{
- return pis.ToList();
+ return pis;
}
- var properties = type.GetProperties().Where(IsWriteable).ToArray();
+ var properties = type.GetProperties().Where(IsWriteable).ToList();
TypeProperties[type.TypeHandle] = properties;
return properties.ToList();
}
@@ -170,14 +164,34 @@ private static PropertyInfo GetSingleKey(string method)
public static T Get(this IDbConnection connection, dynamic id, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
{
var type = typeof(T);
+ var properties = TypePropertiesCache(type);
+ var adapter = GetFormatter(connection);
+
+ var getQueriesKey = new GetQueriesCacheKey(type.TypeHandle, adapter.GetType().TypeHandle);
- if (!GetQueries.TryGetValue(type.TypeHandle, out string sql))
+ if (!GetQueries.TryGetValue(getQueriesKey, out string sql))
{
var key = GetSingleKey(nameof(Get));
- var name = GetTableName(type);
+ var name = type.TableName();
+
+ StringBuilder sqlStringBuilder = new StringBuilder("select ");
+
+ foreach (PropertyInfo property in properties)
+ {
+ adapter.AppendColumnName(sqlStringBuilder, property.ColumnName());
+ sqlStringBuilder.Append(" as ");
+ adapter.AppendColumnName(sqlStringBuilder, property.Name);
+ sqlStringBuilder.AppendLine(",");
+ }
- sql = $"select * from {name} where {key.Name} = @id";
- GetQueries[type.TypeHandle] = sql;
+ sqlStringBuilder.Remove(sqlStringBuilder.Length - 3, 2);
+
+ sqlStringBuilder.Append($" from {name} where ");
+ adapter.AppendColumnNameEqualsValue(sqlStringBuilder, key.ColumnName(), "id");
+
+ sql = sqlStringBuilder.ToString();
+
+ GetQueries[getQueriesKey] = sql;
}
var dynParams = new DynamicParameters();
@@ -194,7 +208,7 @@ public static T Get(this IDbConnection connection, dynamic id, IDbTransaction
obj = ProxyGenerator.GetInterfaceProxy();
- foreach (var property in TypePropertiesCache(type))
+ foreach (var property in properties)
{
var val = res[property.Name];
if (val == null) continue;
@@ -233,14 +247,31 @@ public static IEnumerable GetAll(this IDbConnection connection, IDbTransac
{
var type = typeof(T);
var cacheType = typeof(List);
+ var adapter = GetFormatter(connection);
+ var properties = TypePropertiesCache(type);
+ var getQueriesKey = new GetQueriesCacheKey(cacheType.TypeHandle, adapter.GetType().TypeHandle);
- if (!GetQueries.TryGetValue(cacheType.TypeHandle, out string sql))
+ if (!GetQueries.TryGetValue(getQueriesKey, out string sql))
{
GetSingleKey(nameof(GetAll));
- var name = GetTableName(type);
+ var name = type.TableName();
- sql = "select * from " + name;
- GetQueries[cacheType.TypeHandle] = sql;
+ StringBuilder sqlStringBuilder = new StringBuilder("select ");
+
+ foreach (PropertyInfo property in properties)
+ {
+ adapter.AppendColumnName(sqlStringBuilder, property.ColumnName());
+ sqlStringBuilder.Append(" as ");
+ adapter.AppendColumnName(sqlStringBuilder, property.Name);
+ sqlStringBuilder.AppendLine(",");
+ }
+
+ sqlStringBuilder.Remove(sqlStringBuilder.Length - 3, 2);
+
+ sqlStringBuilder.Append($" from {name} ");
+
+ sql = sqlStringBuilder.ToString();
+ GetQueries[getQueriesKey] = sql;
}
if (!type.IsInterface) return connection.Query(sql, null, transaction, commandTimeout: commandTimeout);
@@ -250,9 +281,9 @@ public static IEnumerable GetAll(this IDbConnection connection, IDbTransac
foreach (IDictionary res in result)
{
var obj = ProxyGenerator.GetInterfaceProxy();
- foreach (var property in TypePropertiesCache(type))
+ foreach (var property in properties)
{
- var val = res[property.Name];
+ var val = res[property.ColumnName()];
if (val == null) continue;
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
@@ -274,39 +305,13 @@ public static IEnumerable GetAll(this IDbConnection connection, IDbTransac
/// Specify a custom table name mapper based on the POCO type name
///
#pragma warning disable CA2211 // Non-constant fields should not be visible - I agree with you, but we can't do that until we break the API
- public static TableNameMapperDelegate TableNameMapper;
-#pragma warning restore CA2211 // Non-constant fields should not be visible
-
- private static string GetTableName(Type type)
+ [Obsolete("Use TypeExtensions.TableNameMapper instead")]
+ public static TypeExtensions.TableNameMapperDelegate TableNameMapper
{
- if (TypeTableName.TryGetValue(type.TypeHandle, out string name)) return name;
-
- if (TableNameMapper != null)
- {
- name = TableNameMapper(type);
- }
- else
- {
- //NOTE: This as dynamic trick falls back to handle both our own Table-attribute as well as the one in EntityFramework
- var tableAttrName =
- type.GetCustomAttribute(false)?.Name
- ?? (type.GetCustomAttributes(false).FirstOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic)?.Name;
-
- if (tableAttrName != null)
- {
- name = tableAttrName;
- }
- else
- {
- name = type.Name + "s";
- if (type.IsInterface && name.StartsWith("I"))
- name = name.Substring(1);
- }
- }
-
- TypeTableName[type.TypeHandle] = name;
- return name;
+ get => TypeExtensions.TableNameMapper;
+ set => TypeExtensions.TableNameMapper = value;
}
+#pragma warning restore CA2211 // Non-constant fields should not be visible
///
/// Inserts an entity into table "Ts" and returns identity id or number of inserted rows if inserting a list.
@@ -342,7 +347,7 @@ public static long Insert(this IDbConnection connection, T entityToInsert, ID
}
}
- var name = GetTableName(type);
+ var name = type.TableName();
var sbColumnList = new StringBuilder(null);
var allProperties = TypePropertiesCache(type);
var keyProperties = KeyPropertiesCache(type);
@@ -354,7 +359,7 @@ public static long Insert(this IDbConnection connection, T entityToInsert, ID
for (var i = 0; i < allPropertiesExceptKeyAndComputed.Count; i++)
{
var property = allPropertiesExceptKeyAndComputed[i];
- adapter.AppendColumnName(sbColumnList, property.Name); //fix for issue #336
+ adapter.AppendColumnName(sbColumnList, property.ColumnName()); //fix for issue #336
if (i < allPropertiesExceptKeyAndComputed.Count - 1)
sbColumnList.Append(", ");
}
@@ -427,7 +432,7 @@ public static bool Update(this IDbConnection connection, T entityToUpdate, ID
if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0)
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
- var name = GetTableName(type);
+ var name = type.TableName();
var sb = new StringBuilder();
sb.AppendFormat("update {0} set ", name);
@@ -442,7 +447,7 @@ public static bool Update(this IDbConnection connection, T entityToUpdate, ID
for (var i = 0; i < nonIdProps.Count; i++)
{
var property = nonIdProps[i];
- adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336
+ adapter.AppendColumnNameEqualsValue(sb, property.ColumnName(), property.Name); //fix for issue #336
if (i < nonIdProps.Count - 1)
sb.Append(", ");
}
@@ -450,7 +455,7 @@ public static bool Update(this IDbConnection connection, T entityToUpdate, ID
for (var i = 0; i < keyProperties.Count; i++)
{
var property = keyProperties[i];
- adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336
+ adapter.AppendColumnNameEqualsValue(sb, property.ColumnName(), property.Name); //fix for issue #336
if (i < keyProperties.Count - 1)
sb.Append(" and ");
}
@@ -496,7 +501,7 @@ public static bool Delete(this IDbConnection connection, T entityToDelete, ID
if (keyProperties.Count == 0 && explicitKeyProperties.Count == 0)
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
- var name = GetTableName(type);
+ var name = type.TableName();
keyProperties.AddRange(explicitKeyProperties);
var sb = new StringBuilder();
@@ -507,7 +512,7 @@ public static bool Delete(this IDbConnection connection, T entityToDelete, ID
for (var i = 0; i < keyProperties.Count; i++)
{
var property = keyProperties[i];
- adapter.AppendColumnNameEqualsValue(sb, property.Name); //fix for issue #336
+ adapter.AppendColumnNameEqualsValue(sb, property.ColumnName(), property.Name); //fix for issue #336
if (i < keyProperties.Count - 1)
sb.Append(" and ");
}
@@ -526,7 +531,7 @@ public static bool Delete(this IDbConnection connection, T entityToDelete, ID
public static bool DeleteAll(this IDbConnection connection, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
{
var type = typeof(T);
- var name = GetTableName(type);
+ var name = type.TableName();
var statement = $"delete from {name}";
var deleted = connection.Execute(statement, null, transaction, commandTimeout);
return deleted > 0;
@@ -721,6 +726,27 @@ public TableAttribute(string tableName)
public string Name { get; set; }
}
+ ///
+ /// Defines the name of a column to use in Dapper.Contrib commands.
+ ///
+ [AttributeUsage(AttributeTargets.Property, Inherited = true)]
+ public class ColumnAttribute : Attribute
+ {
+ ///
+ /// Creates a column mapping to a specific name for Dapper.Contrib commands
+ ///
+ /// The name of this column in the database.
+ public ColumnAttribute(string columnName)
+ {
+ Name = columnName;
+ }
+
+ ///
+ /// The name of the column in the database
+ ///
+ public string Name { get; set; }
+ }
+
///
/// Specifies that this field is a primary key in the database
///
@@ -765,6 +791,31 @@ public WriteAttribute(bool write)
public class ComputedAttribute : Attribute
{
}
+
+ internal readonly struct GetQueriesCacheKey : IEquatable
+ {
+ public bool Equals(GetQueriesCacheKey other) => DataType.Equals(other.DataType) && AdapterType.Equals(other.AdapterType);
+
+ public override bool Equals(object obj) => obj is GetQueriesCacheKey other && Equals(other);
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (DataType.GetHashCode() * 397) ^ AdapterType.GetHashCode();
+ }
+ }
+
+ public GetQueriesCacheKey(RuntimeTypeHandle dataType, RuntimeTypeHandle adapterType)
+ {
+ DataType = dataType;
+ AdapterType = adapterType;
+ }
+
+ public RuntimeTypeHandle DataType { get; }
+
+ public RuntimeTypeHandle AdapterType { get; }
+ }
}
///
@@ -796,9 +847,10 @@ public partial interface ISqlAdapter
///
/// Adds a column equality to a parameter.
///
- /// The string builder to append to.
+ /// The string builder to append to.
/// The column name.
- void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
+ /// The value parameter name.
+ void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName);
}
///
@@ -851,9 +903,10 @@ public void AppendColumnName(StringBuilder sb, string columnName)
///
/// The string builder to append to.
/// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The value parameter name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName)
{
- sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
+ sb.AppendFormat("[{0}] = @{1}", columnName, propertyName);
}
}
@@ -907,9 +960,10 @@ public void AppendColumnName(StringBuilder sb, string columnName)
///
/// The string builder to append to.
/// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The value parameter name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName)
{
- sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
+ sb.AppendFormat("[{0}] = @{1}", columnName, propertyName);
}
}
@@ -962,9 +1016,10 @@ public void AppendColumnName(StringBuilder sb, string columnName)
///
/// The string builder to append to.
/// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The value parameter name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName)
{
- sb.AppendFormat("`{0}` = @{1}", columnName, columnName);
+ sb.AppendFormat("`{0}` = @{1}", columnName, propertyName);
}
}
@@ -1038,9 +1093,10 @@ public void AppendColumnName(StringBuilder sb, string columnName)
///
/// The string builder to append to.
/// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The value parameter name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName)
{
- sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
+ sb.AppendFormat("\"{0}\" = @{1}", columnName, propertyName);
}
}
@@ -1091,9 +1147,10 @@ public void AppendColumnName(StringBuilder sb, string columnName)
///
/// The string builder to append to.
/// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The value parameter name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName)
{
- sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
+ sb.AppendFormat("\"{0}\" = @{1}", columnName, propertyName);
}
}
@@ -1148,8 +1205,9 @@ public void AppendColumnName(StringBuilder sb, string columnName)
///
/// The string builder to append to.
/// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The value parameter name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName, string propertyName)
{
- sb.AppendFormat("{0} = @{1}", columnName, columnName);
+ sb.AppendFormat("{0} = @{1}", columnName, propertyName);
}
}
diff --git a/src/Dapper.Contrib/TypeExtensions.cs b/src/Dapper.Contrib/TypeExtensions.cs
new file mode 100644
index 00000000..5d7afa90
--- /dev/null
+++ b/src/Dapper.Contrib/TypeExtensions.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Concurrent;
+using System.Linq;
+using System.Reflection;
+
+namespace Dapper.Contrib.Extensions
+{
+ ///
+ /// Map to database table extensions
+ ///
+ public static class TypeExtensions
+ {
+ private static readonly ConcurrentDictionary TypeTableName = new ConcurrentDictionary();
+
+ ///
+ /// The function to get a table name from a given
+ ///
+ /// The to get a table name for.
+ public delegate string TableNameMapperDelegate(Type type);
+
+ ///
+ /// Specify a custom table name mapper based on the POCO type name
+ ///
+#pragma warning disable CA2211 // Non-constant fields should not be visible - I agree with you, but we can't do that until we break the API
+ public static TableNameMapperDelegate TableNameMapper;
+#pragma warning restore CA2211 // Non-constant fields should not be visible
+
+ ///
+ /// Get database table name from
+ ///
+ /// The to get a table name for.
+ public static string TableName(this Type type)
+ {
+ if (TypeTableName.TryGetValue(type.TypeHandle, out string name)) return name;
+
+ if (TableNameMapper != null)
+ {
+ name = TableNameMapper(type);
+ }
+ else
+ {
+ //NOTE: This as dynamic trick falls back to handle both our own Table-attribute as well as the one in EntityFramework
+ var tableAttrName =
+ type.GetCustomAttribute(false)?.Name
+ ?? (type.GetCustomAttributes(false).FirstOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic)?.Name;
+
+ if (tableAttrName != null)
+ {
+ name = tableAttrName;
+ }
+ else
+ {
+ name = type.Name + "s";
+ if (type.IsInterface && name.StartsWith("I"))
+ name = name.Substring(1);
+ }
+ }
+
+ TypeTableName[type.TypeHandle] = name;
+ return name;
+ }
+ }
+}
diff --git a/tests/Dapper.Tests.Contrib/TestSuite.Async.cs b/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
index fcd11802..fc04c76c 100644
--- a/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
@@ -106,7 +106,7 @@ public async Task InsertGetUpdateDeleteWithExplicitKeyAsync()
var o1 = new ObjectX { ObjectXId = guid, Name = "Foo" };
var originalxCount = (await connection.QueryAsync("Select Count(*) From ObjectX").ConfigureAwait(false)).First();
await connection.InsertAsync(o1).ConfigureAwait(false);
- var list1 = (await connection.QueryAsync("select * from ObjectX").ConfigureAwait(false)).ToList();
+ var list1 = (await connection.GetAllAsync().ConfigureAwait(false)).ToList();
Assert.Equal(list1.Count, originalxCount + 1);
o1 = await connection.GetAsync(guid).ConfigureAwait(false);
Assert.Equal(o1.ObjectXId, guid);
@@ -122,7 +122,7 @@ public async Task InsertGetUpdateDeleteWithExplicitKeyAsync()
var o2 = new ObjectY { ObjectYId = id, Name = "Foo" };
var originalyCount = connection.Query("Select Count(*) From ObjectY").First();
await connection.InsertAsync(o2).ConfigureAwait(false);
- var list2 = (await connection.QueryAsync("select * from ObjectY").ConfigureAwait(false)).ToList();
+ var list2 = (await connection.GetAllAsync().ConfigureAwait(false)).ToList();
Assert.Equal(list2.Count, originalyCount + 1);
o2 = await connection.GetAsync(id).ConfigureAwait(false);
Assert.Equal(o2.ObjectYId, id);
@@ -142,12 +142,14 @@ public async Task TableNameAsync()
using (var connection = GetOpenConnection())
{
// tests against "Automobiles" table (Table attribute)
- var id = await connection.InsertAsync(new Car { Name = "VolvoAsync" }).ConfigureAwait(false);
+ var id = await connection.InsertAsync(new Car { Model = "VolvoAsync" }).ConfigureAwait(false);
var car = await connection.GetAsync(id).ConfigureAwait(false);
Assert.NotNull(car);
- Assert.Equal("VolvoAsync", car.Name);
- Assert.True(await connection.UpdateAsync(new Car { Id = id, Name = "SaabAsync" }).ConfigureAwait(false));
- Assert.Equal("SaabAsync", (await connection.GetAsync(id).ConfigureAwait(false)).Name);
+ Assert.Equal("VolvoAsync", car.Model);
+ Assert.Equal("[VolvoAsync]", car.Computed);
+ Assert.True(await connection.UpdateAsync(new Car { Id = id, Model = "SaabAsync" }).ConfigureAwait(false));
+ Assert.Equal("SaabAsync", (await connection.GetAsync(id).ConfigureAwait(false)).Model);
+ Assert.Equal("[SaabAsync]", (await connection.GetAsync(id).ConfigureAwait(false)).Computed);
Assert.True(await connection.DeleteAsync(new Car { Id = id }).ConfigureAwait(false));
Assert.Null(await connection.GetAsync(id).ConfigureAwait(false));
}
@@ -158,10 +160,10 @@ public async Task TestSimpleGetAsync()
{
using (var connection = GetOpenConnection())
{
- var id = await connection.InsertAsync(new User { Name = "Adama", Age = 10 }).ConfigureAwait(false);
+ var id = await connection.InsertAsync(new User { FullName = "Adama", Age = 10 }).ConfigureAwait(false);
var user = await connection.GetAsync(id).ConfigureAwait(false);
Assert.Equal(id, user.Id);
- Assert.Equal("Adama", user.Name);
+ Assert.Equal("Adama", user.FullName);
await connection.DeleteAsync(user).ConfigureAwait(false);
}
}
@@ -175,33 +177,33 @@ public async Task InsertGetUpdateAsync()
var originalCount = (await connection.QueryAsync("select Count(*) from Users").ConfigureAwait(false)).First();
- var id = await connection.InsertAsync(new User { Name = "Adam", Age = 10 }).ConfigureAwait(false);
+ var id = await connection.InsertAsync(new User { FullName = "Adam", Age = 10 }).ConfigureAwait(false);
//get a user with "isdirty" tracking
var user = await connection.GetAsync(id).ConfigureAwait(false);
- Assert.Equal("Adam", user.Name);
+ Assert.Equal("Adam", user.FullName);
Assert.False(await connection.UpdateAsync(user).ConfigureAwait(false)); //returns false if not updated, based on tracking
- user.Name = "Bob";
+ user.FullName = "Bob";
Assert.True(await connection.UpdateAsync(user).ConfigureAwait(false)); //returns true if updated, based on tracking
user = await connection.GetAsync(id).ConfigureAwait(false);
- Assert.Equal("Bob", user.Name);
+ Assert.Equal("Bob", user.FullName);
//get a user with no tracking
var notrackedUser = await connection.GetAsync(id).ConfigureAwait(false);
- Assert.Equal("Bob", notrackedUser.Name);
+ Assert.Equal("Bob", notrackedUser.FullName);
Assert.True(await connection.UpdateAsync(notrackedUser).ConfigureAwait(false));
//returns true, even though user was not changed
- notrackedUser.Name = "Cecil";
+ notrackedUser.FullName = "Cecil";
Assert.True(await connection.UpdateAsync(notrackedUser).ConfigureAwait(false));
- Assert.Equal("Cecil", (await connection.GetAsync(id).ConfigureAwait(false)).Name);
+ Assert.Equal("Cecil", (await connection.GetAsync(id).ConfigureAwait(false)).FullName);
- Assert.Equal((await connection.QueryAsync("select * from Users").ConfigureAwait(false)).Count(), originalCount + 1);
+ Assert.Equal((await connection.GetAllAsync().ConfigureAwait(false)).Count(), originalCount + 1);
Assert.True(await connection.DeleteAsync(user).ConfigureAwait(false));
- Assert.Equal((await connection.QueryAsync("select * from Users").ConfigureAwait(false)).Count(), originalCount);
+ Assert.Equal((await connection.GetAllAsync().ConfigureAwait(false)).Count(), originalCount);
Assert.False(await connection.UpdateAsync(notrackedUser).ConfigureAwait(false)); //returns false, user not found
- Assert.True(await connection.InsertAsync(new User { Name = "Adam", Age = 10 }).ConfigureAwait(false) > originalCount + 1);
+ Assert.True(await connection.InsertAsync(new User { FullName = "Adam", Age = 10 }).ConfigureAwait(false) > originalCount + 1);
}
}
@@ -213,7 +215,7 @@ public async Task InsertCheckKeyAsync()
await connection.DeleteAllAsync().ConfigureAwait(false);
Assert.Null(await connection.GetAsync(3).ConfigureAwait(false));
- var user = new User { Name = "Adamb", Age = 10 };
+ var user = new User { FullName = "Adamb", Age = 10 };
var id = await connection.InsertAsync(user).ConfigureAwait(false);
Assert.Equal(user.Id, id);
}
@@ -230,24 +232,23 @@ public async Task BuilderSelectClauseAsync()
var data = new List(100);
for (var i = 0; i < 100; i++)
{
- var nU = new User { Age = rand.Next(70), Id = i, Name = Guid.NewGuid().ToString() };
+ var nU = new User { Age = rand.Next(70), Id = i, FullName = Guid.NewGuid().ToString() };
data.Add(nU);
nU.Id = await connection.InsertAsync(nU).ConfigureAwait(false);
}
var builder = new SqlBuilder();
var justId = builder.AddTemplate("SELECT /**select**/ FROM Users");
- var all = builder.AddTemplate("SELECT Name, /**select**/, Age FROM Users");
builder.Select("Id");
var ids = await connection.QueryAsync(justId.RawSql, justId.Parameters).ConfigureAwait(false);
- var users = await connection.QueryAsync(all.RawSql, all.Parameters).ConfigureAwait(false);
+ var users = await connection.GetAllAsync().ConfigureAwait(false);
foreach (var u in data)
{
if (!ids.Any(i => u.Id == i)) throw new Exception("Missing ids in select");
- if (!users.Any(a => a.Id == u.Id && a.Name == u.Name && a.Age == u.Age))
+ if (!users.Any(a => a.Id == u.Id && a.FullName == u.FullName && a.Age == u.Age))
throw new Exception("Missing users in select");
}
}
@@ -266,7 +267,7 @@ public async Task BuilderTemplateWithoutCompositionAsync()
{
await connection.DeleteAllAsync().ConfigureAwait(false);
- await connection.InsertAsync(new User { Age = 5, Name = "Testy McTestington" }).ConfigureAwait(false);
+ await connection.InsertAsync(new User { Age = 5, FullName = "Testy McTestington" }).ConfigureAwait(false);
if ((await connection.QueryAsync(template.RawSql, template.Parameters).ConfigureAwait(false)).Single() != 1)
throw new Exception("Query failed");
@@ -298,7 +299,7 @@ private async Task InsertHelperAsync(Func, T> helper)
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -306,7 +307,7 @@ private async Task InsertHelperAsync(Func, T> helper)
var total = await connection.InsertAsync(helper(users)).ConfigureAwait(false);
Assert.Equal(total, numberOfEntities);
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities);
}
}
@@ -336,7 +337,7 @@ private async Task UpdateHelperAsync(Func, T> helper)
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -344,14 +345,14 @@ private async Task UpdateHelperAsync(Func, T> helper)
var total = await connection.InsertAsync(helper(users)).ConfigureAwait(false);
Assert.Equal(total, numberOfEntities);
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities);
foreach (var user in users)
{
- user.Name += " updated";
+ user.FullName += " updated";
}
await connection.UpdateAsync(helper(users)).ConfigureAwait(false);
- var name = connection.Query("select * from Users").First().Name;
+ var name = connection.GetAll().First().FullName;
Assert.Contains("updated", name);
}
}
@@ -381,7 +382,7 @@ private async Task DeleteHelperAsync(Func, T> helper)
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -389,12 +390,12 @@ private async Task DeleteHelperAsync(Func, T> helper)
var total = await connection.InsertAsync(helper(users)).ConfigureAwait(false);
Assert.Equal(total, numberOfEntities);
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities);
var usersToDelete = users.Take(10).ToList();
await connection.DeleteAsync(helper(usersToDelete)).ConfigureAwait(false);
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities - 10);
}
}
@@ -406,7 +407,7 @@ public async Task GetAllAsync()
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -465,8 +466,8 @@ public async Task DeleteAllAsync()
{
await connection.DeleteAllAsync().ConfigureAwait(false);
- var id1 = await connection.InsertAsync(new User { Name = "Alice", Age = 32 }).ConfigureAwait(false);
- var id2 = await connection.InsertAsync(new User { Name = "Bob", Age = 33 }).ConfigureAwait(false);
+ var id1 = await connection.InsertAsync(new User { FullName = "Alice", Age = 32 }).ConfigureAwait(false);
+ var id2 = await connection.InsertAsync(new User { FullName = "Bob", Age = 33 }).ConfigureAwait(false);
await connection.DeleteAllAsync().ConfigureAwait(false);
Assert.Null(await connection.GetAsync(id1).ConfigureAwait(false));
Assert.Null(await connection.GetAsync(id2).ConfigureAwait(false));
diff --git a/tests/Dapper.Tests.Contrib/TestSuite.cs b/tests/Dapper.Tests.Contrib/TestSuite.cs
index 71dbd8ad..826d6c55 100644
--- a/tests/Dapper.Tests.Contrib/TestSuite.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuite.cs
@@ -37,14 +37,16 @@ public interface IUser
{
[Key]
int Id { get; set; }
- string Name { get; set; }
+ [Column("Name")]
+ string FullName { get; set; }
int Age { get; set; }
}
public class User : IUser
{
public int Id { get; set; }
- public string Name { get; set; }
+ [Column("Name")]
+ public string FullName { get; set; }
public int Age { get; set; }
}
@@ -63,7 +65,8 @@ public class NullableDate : INullableDate
public class Person
{
- public int Id { get; set; }
+ [Column("Id")]
+ public int IdProp { get; set; }
public string Name { get; set; }
}
@@ -71,7 +74,8 @@ public class Person
public class Stuff
{
[Key]
- public short TheId { get; set; }
+ [Column("TheId")]
+ public short ShortId { get; set; }
public string Name { get; set; }
public DateTime? Created { get; set; }
}
@@ -80,7 +84,8 @@ public class Stuff
public class Car
{
public int Id { get; set; }
- public string Name { get; set; }
+ [Column("Name")]
+ public string Model { get; set; }
[Computed]
public string Computed { get; set; }
}
@@ -228,7 +233,7 @@ public void InsertGetUpdateDeleteWithExplicitKey()
var o1 = new ObjectX { ObjectXId = guid, Name = "Foo" };
var originalxCount = connection.Query("Select Count(*) From ObjectX").First();
connection.Insert(o1);
- var list1 = connection.Query("select * from ObjectX").ToList();
+ var list1 = connection.GetAll().ToList();
Assert.Equal(list1.Count, originalxCount + 1);
o1 = connection.Get(guid);
Assert.Equal(o1.ObjectXId, guid);
@@ -244,7 +249,7 @@ public void InsertGetUpdateDeleteWithExplicitKey()
var o2 = new ObjectY { ObjectYId = id, Name = "Foo" };
var originalyCount = connection.Query("Select Count(*) From ObjectY").First();
connection.Insert(o2);
- var list2 = connection.Query("select * from ObjectY").ToList();
+ var list2 = connection.GetAll().ToList();
Assert.Equal(list2.Count, originalyCount + 1);
o2 = connection.Get(id);
Assert.Equal(o2.ObjectYId, id);
@@ -281,7 +286,7 @@ public void InsertGetUpdateDeleteWithExplicitKeyNamedId()
const int id = 42;
var o2 = new ObjectZ { Id = id, Name = "Foo" };
connection.Insert(o2);
- var list2 = connection.Query("select * from ObjectZ").ToList();
+ var list2 = connection.GetAll().ToList();
Assert.Single(list2);
o2 = connection.Get(id);
Assert.Equal(o2.Id, id);
@@ -297,7 +302,7 @@ public void ShortIdentity()
var id = connection.Insert(new Stuff { Name = name });
Assert.True(id > 0); // 1-n are valid here, due to parallel tests
var item = connection.Get(id);
- Assert.Equal(item.TheId, (short)id);
+ Assert.Equal(item.ShortId, (short)id);
Assert.Equal(item.Name, name);
}
}
@@ -309,7 +314,7 @@ public void NullDateTime()
{
connection.Insert(new Stuff { Name = "First item" });
connection.Insert(new Stuff { Name = "Second item", Created = DateTime.Now });
- var stuff = connection.Query("select * from Stuff").ToList();
+ var stuff = connection.GetAll().ToList();
Assert.Null(stuff[0].Created);
Assert.NotNull(stuff.Last().Created);
}
@@ -321,13 +326,16 @@ public void TableName()
using (var connection = GetOpenConnection())
{
// tests against "Automobiles" table (Table attribute)
- var id = connection.Insert(new Car { Name = "Volvo" });
+ var id = connection.Insert(new Car { Model = "Volvo" });
var car = connection.Get(id);
Assert.NotNull(car);
- Assert.Equal("Volvo", car.Name);
- Assert.Equal("Volvo", connection.Get(id).Name);
- Assert.True(connection.Update(new Car { Id = (int)id, Name = "Saab" }));
- Assert.Equal("Saab", connection.Get(id).Name);
+ Assert.Equal("Volvo", car.Model);
+ Assert.Equal("[Volvo]", car.Computed);
+ Assert.Equal("Volvo", connection.Get(id).Model);
+ Assert.Equal("[Volvo]", connection.Get(id).Computed);
+ Assert.True(connection.Update(new Car { Id = (int)id, Model = "Saab" }));
+ Assert.Equal("Saab", connection.Get(id).Model);
+ Assert.Equal("[Saab]", connection.Get(id).Computed);
Assert.True(connection.Delete(new Car { Id = (int)id }));
Assert.Null(connection.Get(id));
}
@@ -338,10 +346,10 @@ public void TestSimpleGet()
{
using (var connection = GetOpenConnection())
{
- var id = connection.Insert(new User { Name = "Adama", Age = 10 });
+ var id = connection.Insert(new User { FullName = "Adama", Age = 10 });
var user = connection.Get(id);
Assert.Equal(user.Id, (int)id);
- Assert.Equal("Adama", user.Name);
+ Assert.Equal("Adama", user.FullName);
connection.Delete(user);
}
}
@@ -351,7 +359,7 @@ public void TestClosedConnection()
{
using (var connection = GetConnection())
{
- Assert.True(connection.Insert(new User { Name = "Adama", Age = 10 }) > 0);
+ Assert.True(connection.Insert(new User { FullName = "Adama", Age = 10 }) > 0);
var users = connection.GetAll();
Assert.NotEmpty(users);
}
@@ -382,7 +390,7 @@ private void InsertHelper(Func, T> helper)
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -390,7 +398,7 @@ private void InsertHelper(Func, T> helper)
var total = connection.Insert(helper(users));
Assert.Equal(total, numberOfEntities);
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities);
}
}
@@ -420,7 +428,7 @@ private void UpdateHelper(Func, T> helper)
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -428,14 +436,14 @@ private void UpdateHelper(Func, T> helper)
var total = connection.Insert(helper(users));
Assert.Equal(total, numberOfEntities);
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities);
foreach (var user in users)
{
- user.Name += " updated";
+ user.FullName += " updated";
}
connection.Update(helper(users));
- var name = connection.Query("select * from Users").First().Name;
+ var name = connection.GetAll().First().FullName;
Assert.Contains("updated", name);
}
}
@@ -465,7 +473,7 @@ private void DeleteHelper(Func, T> helper)
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -473,12 +481,12 @@ private void DeleteHelper(Func, T> helper)
var total = connection.Insert(helper(users));
Assert.Equal(total, numberOfEntities);
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities);
var usersToDelete = users.Take(10).ToList();
connection.Delete(helper(usersToDelete));
- users = connection.Query("select * from Users").ToList();
+ users = connection.GetAll().ToList();
Assert.Equal(users.Count, numberOfEntities - 10);
}
}
@@ -492,30 +500,30 @@ public void InsertGetUpdate()
Assert.Null(connection.Get(3));
//insert with computed attribute that should be ignored
- connection.Insert(new Car { Name = "Volvo", Computed = "this property should be ignored" });
+ connection.Insert(new Car { Model = "Volvo", Computed = "this property should be ignored" });
- var id = connection.Insert(new User { Name = "Adam", Age = 10 });
+ var id = connection.Insert(new User { FullName = "Adam", Age = 10 });
//get a user with "isdirty" tracking
var user = connection.Get(id);
- Assert.Equal("Adam", user.Name);
+ Assert.Equal("Adam", user.FullName);
Assert.False(connection.Update(user)); //returns false if not updated, based on tracking
- user.Name = "Bob";
+ user.FullName = "Bob";
Assert.True(connection.Update(user)); //returns true if updated, based on tracking
user = connection.Get(id);
- Assert.Equal("Bob", user.Name);
+ Assert.Equal("Bob", user.FullName);
//get a user with no tracking
var notrackedUser = connection.Get(id);
- Assert.Equal("Bob", notrackedUser.Name);
+ Assert.Equal("Bob", notrackedUser.FullName);
Assert.True(connection.Update(notrackedUser)); //returns true, even though user was not changed
- notrackedUser.Name = "Cecil";
+ notrackedUser.FullName = "Cecil";
Assert.True(connection.Update(notrackedUser));
- Assert.Equal("Cecil", connection.Get(id).Name);
+ Assert.Equal("Cecil", connection.Get(id).FullName);
- Assert.Single(connection.Query("select * from Users"));
+ Assert.Single(connection.GetAll());
Assert.True(connection.Delete(user));
- Assert.Empty(connection.Query("select * from Users"));
+ Assert.Empty(connection.GetAll());
Assert.False(connection.Update(notrackedUser)); //returns false, user not found
}
@@ -557,7 +565,7 @@ public void InsertWithCustomDbType()
[Fact]
public void InsertWithCustomTableNameMapper()
{
- SqlMapperExtensions.TableNameMapper = type =>
+ TypeExtensions.TableNameMapper = type =>
{
switch (type.Name)
{
@@ -590,7 +598,7 @@ public void GetAll()
var users = new List(numberOfEntities);
for (var i = 0; i < numberOfEntities; i++)
- users.Add(new User { Name = "User " + i, Age = i });
+ users.Add(new User { FullName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -635,17 +643,18 @@ public void Transactions()
{
using (var connection = GetOpenConnection())
{
- var id = connection.Insert(new Car { Name = "one car" }); //insert outside transaction
+ var id = connection.Insert(new Car { Model = "one car" }); //insert outside transaction
var tran = connection.BeginTransaction();
var car = connection.Get(id, tran);
- var orgName = car.Name;
- car.Name = "Another car";
+ var orgName = car.Model;
+ car.Model = "Another car";
connection.Update(car, tran);
tran.Rollback();
car = connection.Get(id); //updates should have been rolled back
- Assert.Equal(car.Name, orgName);
+ Assert.Equal(car.Model, orgName);
+ Assert.Equal(car.Computed, $"[{orgName}]");
}
}
#if TRANSCOPE
@@ -672,7 +681,7 @@ public void InsertCheckKey()
using (var connection = GetOpenConnection())
{
Assert.Null(connection.Get(3));
- User user = new User { Name = "Adamb", Age = 10 };
+ User user = new User { FullName = "Adamb", Age = 10 };
int id = (int)connection.Insert(user);
Assert.Equal(user.Id, id);
}
@@ -687,7 +696,7 @@ public void BuilderSelectClause()
var data = new List(100);
for (int i = 0; i < 100; i++)
{
- var nU = new User { Age = rand.Next(70), Id = i, Name = Guid.NewGuid().ToString() };
+ var nU = new User { Age = rand.Next(70), Id = i, FullName = Guid.NewGuid().ToString() };
data.Add(nU);
nU.Id = (int)connection.Insert(nU);
}
@@ -699,12 +708,12 @@ public void BuilderSelectClause()
builder.Select("Id");
var ids = connection.Query(justId.RawSql, justId.Parameters);
- var users = connection.Query(all.RawSql, all.Parameters);
+ var users = connection.GetAll();
foreach (var u in data)
{
if (!ids.Any(i => u.Id == i)) throw new Exception("Missing ids in select");
- if (!users.Any(a => a.Id == u.Id && a.Name == u.Name && a.Age == u.Age)) throw new Exception("Missing users in select");
+ if (!users.Any(a => a.Id == u.Id && a.FullName == u.FullName && a.Age == u.Age)) throw new Exception("Missing users in select");
}
}
}
@@ -721,7 +730,7 @@ public void BuilderTemplateWithoutComposition()
using (var connection = GetOpenConnection())
{
connection.DeleteAll();
- connection.Insert(new User { Age = 5, Name = "Testy McTestington" });
+ connection.Insert(new User { Age = 5, FullName = "Testy McTestington" });
if (connection.Query(template.RawSql, template.Parameters).Single() != 1)
throw new Exception("Query failed");
@@ -746,8 +755,8 @@ public void DeleteAll()
{
using (var connection = GetOpenConnection())
{
- var id1 = connection.Insert(new User { Name = "Alice", Age = 32 });
- var id2 = connection.Insert(new User { Name = "Bob", Age = 33 });
+ var id1 = connection.Insert(new User { FullName = "Alice", Age = 32 });
+ var id2 = connection.Insert(new User { FullName = "Bob", Age = 33 });
Assert.True(connection.DeleteAll());
Assert.Null(connection.Get(id1));
Assert.Null(connection.Get(id2));
diff --git a/tests/Dapper.Tests.Contrib/TestSuites.cs b/tests/Dapper.Tests.Contrib/TestSuites.cs
index 55d4ef5c..2d952030 100644
--- a/tests/Dapper.Tests.Contrib/TestSuites.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuites.cs
@@ -41,7 +41,7 @@ static SqlServerTestSuite()
dropTable("Users");
connection.Execute("CREATE TABLE Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null);");
dropTable("Automobiles");
- connection.Execute("CREATE TABLE Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null);");
+ connection.Execute("CREATE TABLE Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Computed AS Concat('[',Name,']'));");
dropTable("Results");
connection.Execute("CREATE TABLE Results (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, [Order] int not null);");
dropTable("ObjectX");
@@ -61,7 +61,7 @@ static SqlServerTestSuite()
public class MySqlServerTestSuite : TestSuite
{
public static string ConnectionString { get; } =
- GetConnectionString("MySqlConnectionString", "Server=localhost;Database=tests;Uid=test;Pwd=pass;UseAffectedRows=false;");
+ GetConnectionString("MySqlConnectionString", "Server=localhost;Database=test;Uid=root;Pwd=root;UseAffectedRows=false;");
public override IDbConnection GetConnection()
{
@@ -87,7 +87,7 @@ static MySqlServerTestSuite()
dropTable("Users");
connection.Execute("CREATE TABLE Users (Id int not null AUTO_INCREMENT PRIMARY KEY, Name nvarchar(100) not null, Age int not null);");
dropTable("Automobiles");
- connection.Execute("CREATE TABLE Automobiles (Id int not null AUTO_INCREMENT PRIMARY KEY, Name nvarchar(100) not null);");
+ connection.Execute("CREATE TABLE Automobiles (Id int not null AUTO_INCREMENT PRIMARY KEY, Name nvarchar(100) not null, Computed nvarchar(150) GENERATED ALWAYS AS (Concat('[',Name,']')));");
dropTable("Results");
connection.Execute("CREATE TABLE Results (Id int not null AUTO_INCREMENT PRIMARY KEY, Name nvarchar(100) not null, `Order` int not null);");
dropTable("ObjectX");
@@ -130,7 +130,7 @@ static SQLiteTestSuite()
connection.Execute("CREATE TABLE Stuff (TheId integer primary key autoincrement not null, Name nvarchar(100) not null, Created DateTime null) ");
connection.Execute("CREATE TABLE People (Id integer primary key autoincrement not null, Name nvarchar(100) not null) ");
connection.Execute("CREATE TABLE Users (Id integer primary key autoincrement not null, Name nvarchar(100) not null, Age int not null) ");
- connection.Execute("CREATE TABLE Automobiles (Id integer primary key autoincrement not null, Name nvarchar(100) not null) ");
+ connection.Execute("CREATE TABLE Automobiles (Id integer primary key autoincrement not null, Name nvarchar(100) not null, Computed nvarchar(150) GENERATED ALWAYS AS ('[' || Name || ']')) ");
connection.Execute("CREATE TABLE Results (Id integer primary key autoincrement not null, Name nvarchar(100) not null, [Order] int not null) ");
connection.Execute("CREATE TABLE ObjectX (ObjectXId nvarchar(100) not null, Name nvarchar(100) not null) ");
connection.Execute("CREATE TABLE ObjectY (ObjectYId integer not null, Name nvarchar(100) not null) ");