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..ec042df9 100644
--- a/Readme.md
+++ b/Readme.md
@@ -167,6 +167,16 @@ 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
+Support for Snake Casing
+-------
+When Dapper's `DefaultTypeMap.MatchNamesWithUnderscores` is set to true,
+Dapper will match a property named 'EmployeeId' to a
+column named 'employee_id'.
+
+(If using this setting, it's generally best to avoid capitalised acronyms in property
+names. For example, a prroperty named 'EmployeeID' would be mapped to a column
+named 'employee_i_d', which is unlikely to be the desired behavior.)
+
Limitations and caveats
-------
diff --git a/src/Dapper.Contrib/Dapper.Contrib.csproj b/src/Dapper.Contrib/Dapper.Contrib.csproj
index 86a0cbb2..0f99133a 100644
--- a/src/Dapper.Contrib/Dapper.Contrib.csproj
+++ b/src/Dapper.Contrib/Dapper.Contrib.csproj
@@ -10,7 +10,7 @@
$(NoWarn);CA1050
-
+
@@ -19,4 +19,12 @@
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
+
\ No newline at end of file
diff --git a/src/Dapper.Contrib/SqlMapperExtensions.Async.cs b/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
index c93e39a4..1e6db3b4 100644
--- a/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
+++ b/src/Dapper.Contrib/SqlMapperExtensions.Async.cs
@@ -25,13 +25,14 @@ 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 keyType = new GetQueryCacheKey(type.TypeHandle, DefaultTypeMap.MatchNamesWithUnderscores);
+ if (!GetQueries.TryGetValue(keyType, out string sql))
{
var key = GetSingleKey(nameof(GetAsync));
var name = GetTableName(type);
- sql = $"SELECT * FROM {name} WHERE {key.Name} = @id";
- GetQueries[type.TypeHandle] = sql;
+ sql = $"SELECT * FROM {name} WHERE {ColumnMapping.ColumnName(key.Name)} = @id";
+ GetQueries[keyType] = sql;
}
var dynParams = new DynamicParameters();
@@ -49,7 +50,7 @@ public static async Task GetAsync(this IDbConnection connection, dynamic i
foreach (var property in TypePropertiesCache(type))
{
- var val = res[property.Name];
+ var val = res[ColumnMapping.ColumnName(property.Name)];
if (val == null) continue;
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
@@ -83,13 +84,15 @@ public static Task> GetAllAsync(this IDbConnection connection,
var type = typeof(T);
var cacheType = typeof(List);
- if (!GetQueries.TryGetValue(cacheType.TypeHandle, out string sql))
+ var cacheKeyType = new GetQueryCacheKey(cacheType.TypeHandle, DefaultTypeMap.MatchNamesWithUnderscores);
+
+ if (!GetQueries.TryGetValue(cacheKeyType, out string sql))
{
GetSingleKey(nameof(GetAll));
var name = GetTableName(type);
sql = "SELECT * FROM " + name;
- GetQueries[cacheType.TypeHandle] = sql;
+ GetQueries[cacheKeyType] = sql;
}
if (!type.IsInterface)
@@ -108,7 +111,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[ColumnMapping.ColumnName(property.Name)];
if (val == null) continue;
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
diff --git a/src/Dapper.Contrib/SqlMapperExtensions.cs b/src/Dapper.Contrib/SqlMapperExtensions.cs
index 9a30e805..aefff0b3 100644
--- a/src/Dapper.Contrib/SqlMapperExtensions.cs
+++ b/src/Dapper.Contrib/SqlMapperExtensions.cs
@@ -41,6 +41,33 @@ public interface ITableNameMapper
string GetTableName(Type type);
}
+ ///
+ /// Key used for the Get Query cache. A query is deterministic for a type and a
+ /// naming convention.
+ ///
+ public struct GetQueryCacheKey {
+ ///
+ /// Initialise a Cache Key
+ ///
+ /// The Type handle of the returned object
+ /// The naming convention used
+ public GetQueryCacheKey(RuntimeTypeHandle typeHandle, bool isUnderscore)
+ {
+ TypeHandle = typeHandle;
+ IsUnderscore = isUnderscore;
+ }
+
+ ///
+ /// The Type handle of the returned object
+ ///
+ public RuntimeTypeHandle TypeHandle { get; }
+
+ ///
+ /// The naming convention used
+ ///
+ public bool IsUnderscore { get; }
+ };
+
///
/// The function to get a database type from the given .
///
@@ -56,8 +83,8 @@ public interface ITableNameMapper
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 GetQueries = new ConcurrentDictionary();
+ private static readonly ConcurrentDictionary TypeTableName = new ConcurrentDictionary();
private static readonly ISqlAdapter DefaultAdapter = new SqlServerAdapter();
private static readonly Dictionary AdapterDictionary
@@ -171,13 +198,14 @@ public static T Get(this IDbConnection connection, dynamic id, IDbTransaction
{
var type = typeof(T);
- if (!GetQueries.TryGetValue(type.TypeHandle, out string sql))
+ var keyType = new GetQueryCacheKey(type.TypeHandle, DefaultTypeMap.MatchNamesWithUnderscores);
+ if (!GetQueries.TryGetValue(keyType, out string sql))
{
var key = GetSingleKey(nameof(Get));
var name = GetTableName(type);
- sql = $"select * from {name} where {key.Name} = @id";
- GetQueries[type.TypeHandle] = sql;
+ sql = $"select * from {name} where {ColumnMapping.ColumnName(key.Name)} = @id";
+ GetQueries[keyType] = sql;
}
var dynParams = new DynamicParameters();
@@ -196,7 +224,7 @@ public static T Get(this IDbConnection connection, dynamic id, IDbTransaction
foreach (var property in TypePropertiesCache(type))
{
- var val = res[property.Name];
+ var val = res[ColumnMapping.ColumnName(property.Name)];
if (val == null) continue;
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
@@ -234,13 +262,15 @@ public static IEnumerable GetAll(this IDbConnection connection, IDbTransac
var type = typeof(T);
var cacheType = typeof(List);
- if (!GetQueries.TryGetValue(cacheType.TypeHandle, out string sql))
+ var keyType = new GetQueryCacheKey(cacheType.TypeHandle, DefaultTypeMap.MatchNamesWithUnderscores);
+
+ if (!GetQueries.TryGetValue(keyType, out string sql))
{
GetSingleKey(nameof(GetAll));
var name = GetTableName(type);
sql = "select * from " + name;
- GetQueries[cacheType.TypeHandle] = sql;
+ GetQueries[keyType] = sql;
}
if (!type.IsInterface) return connection.Query(sql, null, transaction, commandTimeout: commandTimeout);
@@ -252,7 +282,7 @@ public static IEnumerable GetAll(this IDbConnection connection, IDbTransac
var obj = ProxyGenerator.GetInterfaceProxy();
foreach (var property in TypePropertiesCache(type))
{
- var val = res[property.Name];
+ var val = res[ColumnMapping.ColumnName(property.Name)];
if (val == null) continue;
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
@@ -279,7 +309,9 @@ public static IEnumerable GetAll(this IDbConnection connection, IDbTransac
private static string GetTableName(Type type)
{
- if (TypeTableName.TryGetValue(type.TypeHandle, out string name)) return name;
+ var keyType = new GetQueryCacheKey(type.TypeHandle, DefaultTypeMap.MatchNamesWithUnderscores);
+
+ if (TypeTableName.TryGetValue(keyType, out string name)) return name;
if (TableNameMapper != null)
{
@@ -304,7 +336,7 @@ private static string GetTableName(Type type)
}
}
- TypeTableName[type.TypeHandle] = name;
+ TypeTableName[keyType] = name;
return name;
}
@@ -791,14 +823,14 @@ public partial interface ISqlAdapter
/// Adds the name of a column.
///
/// The string builder to append to.
- /// The column name.
- void AppendColumnName(StringBuilder sb, string columnName);
+ /// The property name.
+ void AppendColumnName(StringBuilder sb, string propertyName);
///
/// Adds a column equality to a parameter.
///
/// The string builder to append to.
- /// The column name.
- void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
+ /// The column name.
+ void AppendColumnNameEqualsValue(StringBuilder sb, string propertyName);
}
///
@@ -840,9 +872,10 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
/// Adds the name of a column.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnName(StringBuilder sb, string propertyName)
{
+ var columnName = ColumnMapping.ColumnName(propertyName);
sb.AppendFormat("[{0}]", columnName);
}
@@ -850,10 +883,11 @@ public void AppendColumnName(StringBuilder sb, string columnName)
/// Adds a column equality to a parameter.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string propertyName)
{
- sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
+ var columnName = ColumnMapping.ColumnName(propertyName);
+ sb.AppendFormat("[{0}] = @{1}", columnName, propertyName);
}
}
@@ -896,9 +930,10 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
/// Adds the name of a column.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnName(StringBuilder sb, string propertyName)
{
+ var columnName = ColumnMapping.ColumnName(propertyName);
sb.AppendFormat("[{0}]", columnName);
}
@@ -906,10 +941,11 @@ public void AppendColumnName(StringBuilder sb, string columnName)
/// Adds a column equality to a parameter.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string propertyName)
{
- sb.AppendFormat("[{0}] = @{1}", columnName, columnName);
+ var columnName = ColumnMapping.ColumnName(propertyName);
+ sb.AppendFormat("[{0}] = @{1}", columnName, propertyName);
}
}
@@ -951,9 +987,10 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
/// Adds the name of a column.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnName(StringBuilder sb, string propertyName)
{
+ var columnName = ColumnMapping.ColumnName(propertyName);
sb.AppendFormat("`{0}`", columnName);
}
@@ -961,10 +998,11 @@ public void AppendColumnName(StringBuilder sb, string columnName)
/// Adds a column equality to a parameter.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string propertyName)
{
- sb.AppendFormat("`{0}` = @{1}", columnName, columnName);
+ var columnName = ColumnMapping.ColumnName(propertyName);
+ sb.AppendFormat("`{0}` = @{1}", columnName, propertyName);
}
}
@@ -1027,9 +1065,10 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
/// Adds the name of a column.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnName(StringBuilder sb, string propertyName)
{
+ var columnName = ColumnMapping.ColumnName(propertyName);
sb.AppendFormat("\"{0}\"", columnName);
}
@@ -1037,10 +1076,11 @@ public void AppendColumnName(StringBuilder sb, string columnName)
/// Adds a column equality to a parameter.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string propertyName)
{
- sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
+ var columnName = ColumnMapping.ColumnName(propertyName);
+ sb.AppendFormat("\"{0}\" = @{1}", columnName, propertyName);
}
}
@@ -1080,9 +1120,10 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
/// Adds the name of a column.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnName(StringBuilder sb, string propertyName)
{
+ var columnName = ColumnMapping.ColumnName(propertyName);
sb.AppendFormat("\"{0}\"", columnName);
}
@@ -1090,10 +1131,11 @@ public void AppendColumnName(StringBuilder sb, string columnName)
/// Adds a column equality to a parameter.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string propertyName)
{
- sb.AppendFormat("\"{0}\" = @{1}", columnName, columnName);
+ var columnName = ColumnMapping.ColumnName(propertyName);
+ sb.AppendFormat("\"{0}\" = @{1}", columnName, propertyName);
}
}
@@ -1137,9 +1179,10 @@ public int Insert(IDbConnection connection, IDbTransaction transaction, int? com
/// Adds the name of a column.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnName(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnName(StringBuilder sb, string propertyName)
{
+ var columnName = ColumnMapping.ColumnName(propertyName);
sb.AppendFormat("{0}", columnName);
}
@@ -1147,9 +1190,48 @@ public void AppendColumnName(StringBuilder sb, string columnName)
/// Adds a column equality to a parameter.
///
/// The string builder to append to.
- /// The column name.
- public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
+ /// The property name.
+ public void AppendColumnNameEqualsValue(StringBuilder sb, string propertyName)
+ {
+ var columnName = ColumnMapping.ColumnName(propertyName);
+ sb.AppendFormat("{0} = @{1}", columnName, propertyName);
+ }
+}
+
+///
+/// Utilities for mapping property names to column names
+///
+public static class ColumnMapping
+{
+ ///
+ /// Converts the property name to a column name,
+ /// respecting the setting
+ ///
+ /// The property name to evaluate
+ /// The corresponding column name.
+ ///
+ /// Underscore Handling was introduced in https://github.com/DapperLib/Dapper/commit/33090c0218383411c3b25fa6cb4cbee38d0f3270
+ ///
+ public static string ColumnName(string propertyName)
{
- sb.AppendFormat("{0} = @{1}", columnName, columnName);
+ return DefaultTypeMap.MatchNamesWithUnderscores
+ ? PascalCaseToSnakeCase(propertyName)
+ : propertyName;
+ }
+
+ ///
+ /// Converts PascalCase to Snake_Case
+ ///
+ /// Text to be transformed
+ /// The Snake_Cased string
+ ///
+ /// Because Dapper itself only uses property-column mappings for data reads,
+ /// it only needed to strip underscores from column names; it did not have to
+ /// decide on a casing convention for column names.
+ /// Typically underscores are used with lower case text.
+ ///
+ public static string PascalCaseToSnakeCase(string pascalCaseString) {
+ return string.Concat(pascalCaseString.Select((character, index)
+ => index > 0 && char.IsUpper(character) ? "_" + character.ToString() : character.ToString())).ToLower();
}
}
diff --git a/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj b/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj
index d217f0ce..3d137142 100644
--- a/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj
+++ b/tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj
@@ -13,11 +13,29 @@
-
-
-
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/tests/Dapper.Tests.Contrib/PascalToSnakeCasingTests.cs b/tests/Dapper.Tests.Contrib/PascalToSnakeCasingTests.cs
new file mode 100644
index 00000000..9d51dfb7
--- /dev/null
+++ b/tests/Dapper.Tests.Contrib/PascalToSnakeCasingTests.cs
@@ -0,0 +1,15 @@
+using Xunit;
+
+namespace Dapper.Tests.Contrib
+{
+ public class PascalToSnakeCasingTests
+ {
+ [Fact]
+ public void ConvertToSnakeCase()
+ {
+ Assert.Equal("full_name", ColumnMapping.PascalCaseToSnakeCase("FullName"));
+ Assert.Equal("the_id", ColumnMapping.PascalCaseToSnakeCase("TheId"));
+ Assert.Equal("i_d", ColumnMapping.PascalCaseToSnakeCase("ID"));
+ }
+ }
+}
diff --git a/tests/Dapper.Tests.Contrib/TestSuite.Async.cs b/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
index fcd11802..bfb903e9 100644
--- a/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuite.Async.cs
@@ -158,10 +158,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 { UserName = "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.UserName);
await connection.DeleteAsync(user).ConfigureAwait(false);
}
}
@@ -175,25 +175,25 @@ 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 { UserName = "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.UserName);
Assert.False(await connection.UpdateAsync(user).ConfigureAwait(false)); //returns false if not updated, based on tracking
- user.Name = "Bob";
+ user.UserName = "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.UserName);
//get a user with no tracking
var notrackedUser = await connection.GetAsync(id).ConfigureAwait(false);
- Assert.Equal("Bob", notrackedUser.Name);
+ Assert.Equal("Bob", notrackedUser.UserName);
Assert.True(await connection.UpdateAsync(notrackedUser).ConfigureAwait(false));
//returns true, even though user was not changed
- notrackedUser.Name = "Cecil";
+ notrackedUser.UserName = "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)).UserName);
Assert.Equal((await connection.QueryAsync("select * from Users").ConfigureAwait(false)).Count(), originalCount + 1);
Assert.True(await connection.DeleteAsync(user).ConfigureAwait(false));
@@ -201,7 +201,7 @@ public async Task InsertGetUpdateAsync()
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 { UserName = "Adam", Age = 10 }).ConfigureAwait(false) > originalCount + 1);
}
}
@@ -213,7 +213,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 { UserName = "Adamb", Age = 10 };
var id = await connection.InsertAsync(user).ConfigureAwait(false);
Assert.Equal(user.Id, id);
}
@@ -230,14 +230,15 @@ 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, UserName = 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");
+ var isUnderscored = DefaultTypeMap.MatchNamesWithUnderscores;
+ var all = builder.AddTemplate($"SELECT User{(isUnderscored ? "_" : "")}Name, /**select**/, Age FROM Users");
builder.Select("Id");
@@ -247,7 +248,7 @@ public async Task BuilderSelectClauseAsync()
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.UserName == u.UserName && 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, UserName = "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 { UserName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -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 { UserName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -348,10 +349,10 @@ private async Task UpdateHelperAsync(Func, T> helper)
Assert.Equal(users.Count, numberOfEntities);
foreach (var user in users)
{
- user.Name += " updated";
+ user.UserName += " updated";
}
await connection.UpdateAsync(helper(users)).ConfigureAwait(false);
- var name = connection.Query("select * from Users").First().Name;
+ var name = connection.Query("select * from Users").First().UserName;
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 { UserName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -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 { UserName = "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 { UserName = "Alice", Age = 32 }).ConfigureAwait(false);
+ var id2 = await connection.InsertAsync(new User { UserName = "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..c5a1ed59 100644
--- a/tests/Dapper.Tests.Contrib/TestSuite.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuite.cs
@@ -37,14 +37,14 @@ public interface IUser
{
[Key]
int Id { get; set; }
- string Name { get; set; }
+ string UserName { get; set; }
int Age { get; set; }
}
public class User : IUser
{
public int Id { get; set; }
- public string Name { get; set; }
+ public string UserName { get; set; }
public int Age { get; set; }
}
@@ -73,7 +73,7 @@ public class Stuff
[Key]
public short TheId { get; set; }
public string Name { get; set; }
- public DateTime? Created { get; set; }
+ public DateTime? CreatedAt { get; set; }
}
[Table("Automobiles")]
@@ -308,10 +308,10 @@ public void NullDateTime()
using (var connection = GetOpenConnection())
{
connection.Insert(new Stuff { Name = "First item" });
- connection.Insert(new Stuff { Name = "Second item", Created = DateTime.Now });
+ connection.Insert(new Stuff { Name = "Second item", CreatedAt = DateTime.Now });
var stuff = connection.Query("select * from Stuff").ToList();
- Assert.Null(stuff[0].Created);
- Assert.NotNull(stuff.Last().Created);
+ Assert.Null(stuff[0].CreatedAt);
+ Assert.NotNull(stuff.Last().CreatedAt);
}
}
@@ -338,10 +338,10 @@ public void TestSimpleGet()
{
using (var connection = GetOpenConnection())
{
- var id = connection.Insert(new User { Name = "Adama", Age = 10 });
+ var id = connection.Insert(new User { UserName = "Adama", Age = 10 });
var user = connection.Get(id);
Assert.Equal(user.Id, (int)id);
- Assert.Equal("Adama", user.Name);
+ Assert.Equal("Adama", user.UserName);
connection.Delete(user);
}
}
@@ -351,7 +351,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 { UserName = "Adama", Age = 10 }) > 0);
var users = connection.GetAll();
Assert.NotEmpty(users);
}
@@ -382,7 +382,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 { UserName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -420,7 +420,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 { UserName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -432,10 +432,10 @@ private void UpdateHelper(Func, T> helper)
Assert.Equal(users.Count, numberOfEntities);
foreach (var user in users)
{
- user.Name += " updated";
+ user.UserName += " updated";
}
connection.Update(helper(users));
- var name = connection.Query("select * from Users").First().Name;
+ var name = connection.Query("select * from Users").First().UserName;
Assert.Contains("updated", name);
}
}
@@ -465,7 +465,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 { UserName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -494,24 +494,24 @@ public void InsertGetUpdate()
//insert with computed attribute that should be ignored
connection.Insert(new Car { Name = "Volvo", Computed = "this property should be ignored" });
- var id = connection.Insert(new User { Name = "Adam", Age = 10 });
+ var id = connection.Insert(new User { UserName = "Adam", Age = 10 });
//get a user with "isdirty" tracking
var user = connection.Get(id);
- Assert.Equal("Adam", user.Name);
+ Assert.Equal("Adam", user.UserName);
Assert.False(connection.Update(user)); //returns false if not updated, based on tracking
- user.Name = "Bob";
+ user.UserName = "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.UserName);
//get a user with no tracking
var notrackedUser = connection.Get(id);
- Assert.Equal("Bob", notrackedUser.Name);
+ Assert.Equal("Bob", notrackedUser.UserName);
Assert.True(connection.Update(notrackedUser)); //returns true, even though user was not changed
- notrackedUser.Name = "Cecil";
+ notrackedUser.UserName = "Cecil";
Assert.True(connection.Update(notrackedUser));
- Assert.Equal("Cecil", connection.Get(id).Name);
+ Assert.Equal("Cecil", connection.Get(id).UserName);
Assert.Single(connection.Query("select * from Users"));
Assert.True(connection.Delete(user));
@@ -590,7 +590,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 { UserName = "User " + i, Age = i });
using (var connection = GetOpenConnection())
{
@@ -672,7 +672,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 { UserName = "Adamb", Age = 10 };
int id = (int)connection.Insert(user);
Assert.Equal(user.Id, id);
}
@@ -687,14 +687,15 @@ 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, UserName = Guid.NewGuid().ToString() };
data.Add(nU);
nU.Id = (int)connection.Insert(nU);
}
var builder = new SqlBuilder();
var justId = builder.AddTemplate("SELECT /**select**/ FROM Users");
- var all = builder.AddTemplate("SELECT Name, /**select**/, Age FROM Users");
+ var isUnderscored = DefaultTypeMap.MatchNamesWithUnderscores;
+ var all = builder.AddTemplate($"SELECT User{(isUnderscored ? "_" : "")}Name, /**select**/, Age FROM Users");
builder.Select("Id");
@@ -704,7 +705,7 @@ public void BuilderSelectClause()
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.UserName == u.UserName && a.Age == u.Age)) throw new Exception("Missing users in select");
}
}
}
@@ -721,7 +722,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, UserName = "Testy McTestington" });
if (connection.Query(template.RawSql, template.Parameters).Single() != 1)
throw new Exception("Query failed");
@@ -746,8 +747,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 { UserName = "Alice", Age = 32 });
+ var id2 = connection.Insert(new User { UserName = "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..2eba9409 100644
--- a/tests/Dapper.Tests.Contrib/TestSuites.cs
+++ b/tests/Dapper.Tests.Contrib/TestSuites.cs
@@ -19,6 +19,22 @@ public class SkippableFactAttribute : FactAttribute
{
}
+
+ ///
+ /// Disaplce parallel running of test suites. Because of the dependency on
+ /// the static property
+ /// parallel running wil break tests using different settings.
+ ///
+ ///
+ /// https://stackoverflow.com/questions/1408175/execute-unit-tests-serially-rather-than-in-parallel
+ /// https://github.com/xunit/visualstudio.xunit/issues/191
+ ///
+ [CollectionDefinition("Sequential", DisableParallelization = true)]
+ public class NonParallelCollectionDefinitionClass
+ {
+ }
+
+ [Collection("Sequential")]
public class SqlServerTestSuite : TestSuite
{
private const string DbName = "tempdb";
@@ -29,17 +45,19 @@ public class SqlServerTestSuite : TestSuite
static SqlServerTestSuite()
{
+ Dapper.DefaultTypeMap.MatchNamesWithUnderscores = false;
+
using (var connection = new SqlConnection(ConnectionString))
{
// ReSharper disable once AccessToDisposedClosure
void dropTable(string name) => connection.Execute($"IF OBJECT_ID('{name}', 'U') IS NOT NULL DROP TABLE [{name}]; ");
connection.Open();
dropTable("Stuff");
- connection.Execute("CREATE TABLE Stuff (TheId int IDENTITY(1,1) not null, Name nvarchar(100) not null, Created DateTime null);");
+ connection.Execute("CREATE TABLE Stuff (TheId int IDENTITY(1,1) not null, Name nvarchar(100) not null, CreatedAt DateTime null);");
dropTable("People");
connection.Execute("CREATE TABLE People (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null);");
dropTable("Users");
- connection.Execute("CREATE TABLE Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null);");
+ connection.Execute("CREATE TABLE Users (Id int IDENTITY(1,1) not null, UserName 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);");
dropTable("Results");
@@ -58,6 +76,49 @@ static SqlServerTestSuite()
}
}
+ [Collection("Sequential")]
+ public class SqlServerUnderscoreTestSuite : TestSuite
+ {
+ private const string DbName = "tempdb";
+ public static string ConnectionString =>
+ GetConnectionString("SqlServerConnectionString", $"Data Source=.;Initial Catalog={DbName};Integrated Security=True");
+
+ public override IDbConnection GetConnection() => new SqlConnection(ConnectionString);
+
+ static SqlServerUnderscoreTestSuite()
+ {
+ Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
+
+ using (var connection = new SqlConnection(ConnectionString))
+ {
+ // ReSharper disable once AccessToDisposedClosure
+ void dropTable(string name) => connection.Execute($"IF OBJECT_ID('{name}', 'U') IS NOT NULL DROP TABLE [{name}]; ");
+ connection.Open();
+ dropTable("Stuff");
+ connection.Execute("CREATE TABLE Stuff (the_id int IDENTITY(1,1) not null, name nvarchar(100) not null, created_at DateTime null);");
+ dropTable("People");
+ connection.Execute("CREATE TABLE People (id int IDENTITY(1,1) not null, name nvarchar(100) not null);");
+ dropTable("Users");
+ connection.Execute("CREATE TABLE Users (id int IDENTITY(1,1) not null, user_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);");
+ 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");
+ connection.Execute("CREATE TABLE ObjectX (object_x_Id nvarchar(100) not null, name nvarchar(100) not null);");
+ dropTable("ObjectY");
+ connection.Execute("CREATE TABLE ObjectY (object_y_Id int not null, name nvarchar(100) not null);");
+ dropTable("ObjectZ");
+ connection.Execute("CREATE TABLE ObjectZ (id int not null, name nvarchar(100) not null);");
+ dropTable("GenericType");
+ connection.Execute("CREATE TABLE GenericType (id nvarchar(100) not null, name nvarchar(100) not null);");
+ dropTable("NullableDates");
+ connection.Execute("CREATE TABLE NullableDates (id int IDENTITY(1,1) not null, date_value DateTime null);");
+ }
+ }
+ }
+
+ [Collection("Sequential")]
public class MySqlServerTestSuite : TestSuite
{
public static string ConnectionString { get; } =
@@ -73,6 +134,8 @@ public override IDbConnection GetConnection()
static MySqlServerTestSuite()
{
+ Dapper.DefaultTypeMap.MatchNamesWithUnderscores = false;
+
try
{
using (var connection = new MySqlConnection(ConnectionString))
@@ -85,7 +148,7 @@ static MySqlServerTestSuite()
dropTable("People");
connection.Execute("CREATE TABLE People (Id int not null AUTO_INCREMENT PRIMARY KEY, Name nvarchar(100) not null);");
dropTable("Users");
- connection.Execute("CREATE TABLE Users (Id int not null AUTO_INCREMENT PRIMARY KEY, Name nvarchar(100) not null, Age int not null);");
+ connection.Execute("CREATE TABLE Users (Id int not null AUTO_INCREMENT PRIMARY KEY, UserName 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);");
dropTable("Results");
@@ -112,6 +175,40 @@ static MySqlServerTestSuite()
}
}
+ [Collection("Sequential")]
+ public class SQLiteUnderscoreTestSuite : TestSuite
+ {
+ // Use a different file name to the SQLiteTestSuite to avoid the test runner attempting to interact with the same file.
+ private const string FileName = "Test.DB.Undescore.sqlite";
+ public static string ConnectionString => $"Filename=./{FileName};Mode=ReadWriteCreate;";
+ public override IDbConnection GetConnection() => new SqliteConnection(ConnectionString);
+
+ static SQLiteUnderscoreTestSuite()
+ {
+ Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
+
+ if (File.Exists(FileName))
+ {
+ File.Delete(FileName);
+ }
+ using (var connection = new SqliteConnection(ConnectionString))
+ {
+ connection.Open();
+ connection.Execute("CREATE TABLE Stuff (the_id integer primary key autoincrement not null, Name nvarchar(100) not null, created_at 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, user_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 Results (id integer primary key autoincrement not null, name nvarchar(100) not null, [order] int not null) ");
+ connection.Execute("CREATE TABLE ObjectX (object_x_id nvarchar(100) not null, name nvarchar(100) not null) ");
+ connection.Execute("CREATE TABLE ObjectY (object_y_id integer not null, name nvarchar(100) not null) ");
+ connection.Execute("CREATE TABLE ObjectZ (id integer not null, name nvarchar(100) not null) ");
+ connection.Execute("CREATE TABLE GenericType (id nvarchar(100) not null, name nvarchar(100) not null) ");
+ connection.Execute("CREATE TABLE NullableDates (id integer primary key autoincrement not null, date_value DateTime) ");
+ }
+ }
+ }
+
+ [Collection("Sequential")]
public class SQLiteTestSuite : TestSuite
{
private const string FileName = "Test.DB.sqlite";
@@ -120,6 +217,8 @@ public class SQLiteTestSuite : TestSuite
static SQLiteTestSuite()
{
+ Dapper.DefaultTypeMap.MatchNamesWithUnderscores = false;
+
if (File.Exists(FileName))
{
File.Delete(FileName);
@@ -127,9 +226,9 @@ static SQLiteTestSuite()
using (var connection = new SqliteConnection(ConnectionString))
{
connection.Open();
- connection.Execute("CREATE TABLE Stuff (TheId integer primary key autoincrement not null, Name nvarchar(100) not null, Created DateTime null) ");
+ connection.Execute("CREATE TABLE Stuff (TheId integer primary key autoincrement not null, Name nvarchar(100) not null, CreatedAt 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 Users (Id integer primary key autoincrement not null, UserName 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 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) ");
@@ -143,7 +242,8 @@ static SQLiteTestSuite()
#if SQLCE
- public class SqlCETestSuite : TestSuite
+ [Collection("Sequential")]
+ public class SqlCETestSuite : TestSuite
{
const string FileName = "Test.DB.sdf";
public static string ConnectionString => $"Data Source={FileName};";
@@ -160,9 +260,9 @@ static SqlCETestSuite()
using (var connection = new SqlCeConnection(ConnectionString))
{
connection.Open();
- connection.Execute(@"CREATE TABLE Stuff (TheId int IDENTITY(1,1) not null, Name nvarchar(100) not null, Created DateTime null) ");
+ connection.Execute(@"CREATE TABLE Stuff (TheId int IDENTITY(1,1) not null, Name nvarchar(100) not null, CreatedAt DateTime null) ");
connection.Execute(@"CREATE TABLE People (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) ");
- connection.Execute(@"CREATE TABLE Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null) ");
+ connection.Execute(@"CREATE TABLE Users (Id int IDENTITY(1,1) not null, User_Name nvarchar(100) not null, Age int not null) ");
connection.Execute(@"CREATE TABLE Automobiles (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null) ");
connection.Execute(@"CREATE TABLE Results (Id int IDENTITY(1,1) 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) ");
diff --git a/tests/Dapper.Tests.Contrib/xunit.runner.json b/tests/Dapper.Tests.Contrib/xunit.runner.json
index f2314377..b1b3aacf 100644
--- a/tests/Dapper.Tests.Contrib/xunit.runner.json
+++ b/tests/Dapper.Tests.Contrib/xunit.runner.json
@@ -1,4 +1,5 @@
{
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
- "shadowCopy": false
+ "shadowCopy": false,
+ "parallelizeTestCollections": false
}
\ No newline at end of file