diff --git a/Dapper.SimpleCRUD/SimpleCRUDAsync.cs b/Dapper.SimpleCRUD/SimpleCRUDAsync.cs index ff70770..437e4a5 100644 --- a/Dapper.SimpleCRUD/SimpleCRUDAsync.cs +++ b/Dapper.SimpleCRUD/SimpleCRUDAsync.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace Dapper @@ -28,6 +29,24 @@ public static partial class SimpleCRUD /// /// Returns a single entity by a single id from table T. public static async Task GetAsync(this IDbConnection connection, object id, IDbTransaction transaction = null, int? commandTimeout = null) + { + DynamicParameters dynamicParameters = new DynamicParameters(); + var sb = _GetAsync(id, dynamicParameters); + + var query = await connection.QueryAsync(sb.ToString(), dynamicParameters, transaction, commandTimeout); + return query.FirstOrDefault(); + } + + public static async Task GetAsync(this IDbConnection connection, object id, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var dynamicParameters = new DynamicParameters(); + var sb = _GetAsync(id, dynamicParameters); + + var query = await connection.QueryAsync(new CommandDefinition(sb.ToString(), dynamicParameters, transaction, commandTimeout, cancellationToken: token ?? default)); + return query.FirstOrDefault(); + } + + private static StringBuilder _GetAsync(object id, DynamicParameters dynParms) { var currenttype = typeof(T); var idProps = GetIdProperties(currenttype).ToList(); @@ -49,7 +68,6 @@ public static async Task GetAsync(this IDbConnection connection, object id sb.AppendFormat("{0} = @{1}", GetColumnName(idProps[i]), idProps[i].Name); } - var dynParms = new DynamicParameters(); if (idProps.Count == 1) dynParms.Add("@" + idProps.First().Name, id); else @@ -60,9 +78,7 @@ public static async Task GetAsync(this IDbConnection connection, object id if (Debugger.IsAttached) Trace.WriteLine(String.Format("Get<{0}>: {1} with Id: {2}", currenttype, sb, id)); - - var query = await connection.QueryAsync(sb.ToString(), dynParms, transaction, commandTimeout); - return query.FirstOrDefault(); + return sb; } /// @@ -79,6 +95,18 @@ public static async Task GetAsync(this IDbConnection connection, object id /// /// Gets a list of entities with optional exact match where conditions public static Task> GetListAsync(this IDbConnection connection, object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null) + { + var sb = _GetListAsync(whereConditions); + return connection.QueryAsync(sb.ToString(), whereConditions, transaction, commandTimeout); + } + + public static Task> GetListAsync(this IDbConnection connection, object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _GetListAsync(whereConditions); + return connection.QueryAsync(new CommandDefinition(sb.ToString(), whereConditions, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static StringBuilder _GetListAsync(object whereConditions) { var currenttype = typeof(T); var name = GetTableName(currenttype); @@ -98,8 +126,7 @@ public static Task> GetListAsync(this IDbConnection connection if (Debugger.IsAttached) Trace.WriteLine(String.Format("GetList<{0}>: {1}", currenttype, sb)); - - return connection.QueryAsync(sb.ToString(), whereConditions, transaction, commandTimeout); + return sb; } /// @@ -118,6 +145,18 @@ public static Task> GetListAsync(this IDbConnection connection /// /// Gets a list of entities with optional SQL where conditions public static Task> GetListAsync(this IDbConnection connection, string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null) + { + var sb = _GetListAsync(conditions); + return connection.QueryAsync(sb.ToString(), parameters, transaction, commandTimeout); + } + + public static Task> GetListAsync(this IDbConnection connection, string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _GetListAsync(conditions); + return connection.QueryAsync(new CommandDefinition(sb.ToString(), parameters, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static StringBuilder _GetListAsync(string conditions) { var currenttype = typeof(T); var name = GetTableName(currenttype); @@ -132,8 +171,7 @@ public static Task> GetListAsync(this IDbConnection connection if (Debugger.IsAttached) Trace.WriteLine(String.Format("GetList<{0}>: {1}", currenttype, sb)); - - return connection.QueryAsync(sb.ToString(), parameters, transaction, commandTimeout); + return sb; } /// @@ -146,7 +184,12 @@ public static Task> GetListAsync(this IDbConnection connection /// Gets a list of all entities public static Task> GetListAsync(this IDbConnection connection) { - return connection.GetListAsync(new { }); + return connection.GetListAsync(new { }, null, null); + } + + public static Task> GetListAsync(this IDbConnection connection, CancellationToken? token = null) + { + return connection.GetListAsync(new { }, null, null, token); } /// @@ -168,6 +211,18 @@ public static Task> GetListAsync(this IDbConnection connection /// /// Gets a list of entities with optional exact match where conditions public static Task> GetListPagedAsync(this IDbConnection connection, int pageNumber, int rowsPerPage, string conditions, string orderby, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null) + { + var query = _GetListPagedAsync(pageNumber, rowsPerPage, conditions, orderby); + return connection.QueryAsync(query, parameters, transaction, commandTimeout); + } + + public static Task> GetListPagedAsync(this IDbConnection connection, int pageNumber, int rowsPerPage, string conditions, string orderby, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var query = _GetListPagedAsync(pageNumber, rowsPerPage, conditions, orderby); + return connection.QueryAsync(new CommandDefinition(query, parameters, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static string _GetListPagedAsync(int pageNumber, int rowsPerPage, string conditions, string orderby) { if (string.IsNullOrEmpty(_getPagedListSql)) throw new Exception("GetListPage is not supported with the current SQL Dialect"); @@ -197,8 +252,7 @@ public static Task> GetListPagedAsync(this IDbConnection conne if (Debugger.IsAttached) Trace.WriteLine(String.Format("GetListPaged<{0}>: {1}", currenttype, query)); - - return connection.QueryAsync(query, parameters, transaction, commandTimeout); + return query; } /// @@ -220,6 +274,11 @@ public static Task> GetListPagedAsync(this IDbConnection conne return InsertAsync(connection, entityToInsert, transaction, commandTimeout); } + public static Task InsertAsync(this IDbConnection connection, TEntity entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + return InsertAsync(connection, entityToInsert, transaction, commandTimeout, token); + } + /// /// Inserts a row into the database, using ONLY the properties defined by TEntity /// By default inserts into the table matching the class name @@ -239,7 +298,7 @@ public static async Task InsertAsync(this IDbConnection con if (typeof(TEntity).IsInterface) //FallBack to BaseType Generic Method : https://stackoverflow.com/questions/4101784/calling-a-generic-method-with-a-dynamic-type { return await (Task)typeof(SimpleCRUD) - .GetMethods().Where(methodInfo => methodInfo.Name == nameof(InsertAsync) && methodInfo.GetGenericArguments().Count() == 2).Single() + .GetMethods().Where(methodInfo => methodInfo.Name == nameof(InsertAsync) && methodInfo.GetGenericArguments().Count() == 2 && methodInfo.GetParameters().Length == 4).Single() .MakeGenericMethod(new Type[] { typeof(TKey), entityToInsert.GetType() }) .Invoke(null, new object[] { connection, entityToInsert, transaction, commandTimeout }); } @@ -302,6 +361,75 @@ public static async Task InsertAsync(this IDbConnection con var r = await connection.QueryAsync(sb.ToString(), entityToInsert, transaction, commandTimeout); return (TKey)r.First().id; } + + public static async Task InsertAsync(this IDbConnection connection, TEntity entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + if (typeof(TEntity).IsInterface) //FallBack to BaseType Generic Method : https://stackoverflow.com/questions/4101784/calling-a-generic-method-with-a-dynamic-type + { + return await (Task)typeof(SimpleCRUD) + .GetMethods().Where(methodInfo => methodInfo.Name == nameof(InsertAsync) && methodInfo.GetGenericArguments().Count() == 2 && methodInfo.GetParameters().Length == 5).Single() + .MakeGenericMethod(new Type[] { typeof(TKey), entityToInsert.GetType() }) + .Invoke(null, new object[] { connection, entityToInsert, transaction, commandTimeout, token }); + } + var idProps = GetIdProperties(entityToInsert).ToList(); + + if (!idProps.Any()) + throw new ArgumentException("Insert only supports an entity with a [Key] or Id property"); + + var keyHasPredefinedValue = false; + var baseType = typeof(TKey); + var underlyingType = Nullable.GetUnderlyingType(baseType); + var keytype = underlyingType ?? baseType; + if (keytype != typeof(int) && keytype != typeof(uint) && keytype != typeof(long) && keytype != typeof(ulong) && keytype != typeof(short) && keytype != typeof(ushort) && keytype != typeof(Guid) && keytype != typeof(string)) + { + throw new Exception("Invalid return type"); + } + + var name = GetTableName(entityToInsert); + var sb = new StringBuilder(); + sb.AppendFormat("insert into {0}", name); + sb.Append(" ("); + BuildInsertParameters(sb); + sb.Append(") "); + sb.Append("values"); + sb.Append(" ("); + BuildInsertValues(sb); + sb.Append(")"); + + if (keytype == typeof(Guid)) + { + var guidvalue = (Guid)idProps.First().GetValue(entityToInsert, null); + if (guidvalue == Guid.Empty) + { + var newguid = SequentialGuid(); + idProps.First().SetValue(entityToInsert, newguid, null); + } + else + { + keyHasPredefinedValue = true; + } + } + + if ((keytype == typeof(int) || keytype == typeof(long)) && Convert.ToInt64(idProps.First().GetValue(entityToInsert, null)) == 0) + { + sb.Append(";" + _getIdentitySql); + } + else + { + keyHasPredefinedValue = true; + } + + if (Debugger.IsAttached) + Trace.WriteLine(String.Format("Insert: {0}", sb)); + + if (keytype == typeof(Guid) || keyHasPredefinedValue) + { + await connection.ExecuteAsync(new CommandDefinition(sb.ToString(), entityToInsert, transaction, commandTimeout, cancellationToken: token ?? default)); + return (TKey)idProps.First().GetValue(entityToInsert, null); + } + var r = await connection.QueryAsync(new CommandDefinition(sb.ToString(), entityToInsert, transaction, commandTimeout, cancellationToken: token ?? default)); + return (TKey)r.First().id; + } /// /// Updates a record or records in the database asynchronously @@ -317,7 +445,7 @@ public static async Task InsertAsync(this IDbConnection con /// /// /// The number of affected records - public static async Task UpdateAsync(this IDbConnection connection, TEntity entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null, System.Threading.CancellationToken? token = null) + public static async Task UpdateAsync(this IDbConnection connection, TEntity entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) { if (typeof(TEntity).IsInterface) //FallBack to BaseType Generic Method : https://stackoverflow.com/questions/4101784/calling-a-generic-method-with-a-dynamic-type { @@ -362,6 +490,18 @@ public static async Task UpdateAsync(this IDbConnection connection /// /// The number of records affected public static Task DeleteAsync(this IDbConnection connection, T entityToDelete, IDbTransaction transaction = null, int? commandTimeout = null) + { + var sb = _DeleteAsync(entityToDelete); + return connection.ExecuteAsync(sb.ToString(), entityToDelete, transaction, commandTimeout); + } + + public static Task DeleteAsync(this IDbConnection connection, T entityToDelete, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _DeleteAsync(entityToDelete); + return connection.ExecuteAsync(new CommandDefinition(sb.ToString(), entityToDelete, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static StringBuilder _DeleteAsync(T entityToDelete) { var idProps = GetIdProperties(entityToDelete).ToList(); @@ -378,8 +518,7 @@ public static Task DeleteAsync(this IDbConnection connection, T entityTo if (Debugger.IsAttached) Trace.WriteLine(String.Format("Delete: {0}", sb)); - - return connection.ExecuteAsync(sb.ToString(), entityToDelete, transaction, commandTimeout); + return sb; } /// @@ -397,6 +536,18 @@ public static Task DeleteAsync(this IDbConnection connection, T entityTo /// /// The number of records affected public static Task DeleteAsync(this IDbConnection connection, object id, IDbTransaction transaction = null, int? commandTimeout = null) + { + var sb = _DeleteAsync(id, out var dynParms); + return connection.ExecuteAsync(sb.ToString(), dynParms, transaction, commandTimeout); + } + + public static Task DeleteAsync(this IDbConnection connection, object id, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _DeleteAsync(id, out var dynParms); + return connection.ExecuteAsync(new CommandDefinition(sb.ToString(), dynParms, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static StringBuilder _DeleteAsync(object id, out DynamicParameters dynParms) { var currenttype = typeof(T); var idProps = GetIdProperties(currenttype).ToList(); @@ -416,7 +567,7 @@ public static Task DeleteAsync(this IDbConnection connection, object id, sb.AppendFormat("{0} = @{1}", GetColumnName(idProps[i]), idProps[i].Name); } - var dynParms = new DynamicParameters(); + dynParms = new DynamicParameters(); if (idProps.Count == 1) dynParms.Add("@" + idProps.First().Name, id); else @@ -427,8 +578,7 @@ public static Task DeleteAsync(this IDbConnection connection, object id, if (Debugger.IsAttached) Trace.WriteLine(String.Format("Delete<{0}> {1}", currenttype, sb)); - - return connection.ExecuteAsync(sb.ToString(), dynParms, transaction, commandTimeout); + return sb; } @@ -449,7 +599,18 @@ public static Task DeleteAsync(this IDbConnection connection, object id, /// The number of records affected public static Task DeleteListAsync(this IDbConnection connection, object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null) { + var sb = _DeleteListAsync(whereConditions); + return connection.ExecuteAsync(sb.ToString(), whereConditions, transaction, commandTimeout); + } + + public static Task DeleteListAsync(this IDbConnection connection, object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _DeleteListAsync(whereConditions); + return connection.ExecuteAsync(new CommandDefinition(sb.ToString(), whereConditions, transaction, commandTimeout, cancellationToken: token ?? default)); + } + private static StringBuilder _DeleteListAsync(object whereConditions) + { var currenttype = typeof(T); var name = GetTableName(currenttype); @@ -464,8 +625,7 @@ public static Task DeleteListAsync(this IDbConnection connection, object if (Debugger.IsAttached) Trace.WriteLine(String.Format("DeleteList<{0}> {1}", currenttype, sb)); - - return connection.ExecuteAsync(sb.ToString(), whereConditions, transaction, commandTimeout); + return sb; } /// @@ -484,6 +644,18 @@ public static Task DeleteListAsync(this IDbConnection connection, object /// /// The number of records affected public static Task DeleteListAsync(this IDbConnection connection, string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null) + { + var sb = _DeleteListAsync(conditions); + return connection.ExecuteAsync(sb.ToString(), parameters, transaction, commandTimeout); + } + + public static Task DeleteListAsync(this IDbConnection connection, string conditions, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _DeleteListAsync(conditions); + return connection.ExecuteAsync(new CommandDefinition(sb.ToString(), parameters, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static StringBuilder _DeleteListAsync(string conditions) { if (string.IsNullOrEmpty(conditions)) throw new ArgumentException("DeleteList requires a where clause"); @@ -499,8 +671,7 @@ public static Task DeleteListAsync(this IDbConnection connection, string if (Debugger.IsAttached) Trace.WriteLine(String.Format("DeleteList<{0}> {1}", currenttype, sb)); - - return connection.ExecuteAsync(sb.ToString(), parameters, transaction, commandTimeout); + return sb; } /// @@ -518,6 +689,18 @@ public static Task DeleteListAsync(this IDbConnection connection, string /// /// Returns a count of records. public static Task RecordCountAsync(this IDbConnection connection, string conditions = "", object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null) + { + var sb = _RecordCountAsync(conditions); + return connection.ExecuteScalarAsync(sb.ToString(), parameters, transaction, commandTimeout); + } + + public static Task RecordCountAsync(this IDbConnection connection, string conditions = "", object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _RecordCountAsync(conditions); + return connection.ExecuteScalarAsync(new CommandDefinition(sb.ToString(), parameters, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static StringBuilder _RecordCountAsync(string conditions) { var currenttype = typeof(T); var name = GetTableName(currenttype); @@ -528,8 +711,7 @@ public static Task RecordCountAsync(this IDbConnection connection, strin if (Debugger.IsAttached) Trace.WriteLine(String.Format("RecordCount<{0}>: {1}", currenttype, sb)); - - return connection.ExecuteScalarAsync(sb.ToString(), parameters, transaction, commandTimeout); + return sb; } /// @@ -546,6 +728,18 @@ public static Task RecordCountAsync(this IDbConnection connection, strin /// /// Returns a count of records. public static Task RecordCountAsync(this IDbConnection connection, object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null) + { + var sb = _RecordCountAsync(whereConditions); + return connection.ExecuteScalarAsync(sb.ToString(), whereConditions, transaction, commandTimeout); + } + + public static Task RecordCountAsync(this IDbConnection connection, object whereConditions, IDbTransaction transaction = null, int? commandTimeout = null, CancellationToken? token = null) + { + var sb = _RecordCountAsync(whereConditions); + return connection.ExecuteScalarAsync(new CommandDefinition(sb.ToString(), whereConditions, transaction, commandTimeout, cancellationToken: token ?? default)); + } + + private static StringBuilder _RecordCountAsync(object whereConditions) { var currenttype = typeof(T); var name = GetTableName(currenttype); @@ -562,8 +756,7 @@ public static Task RecordCountAsync(this IDbConnection connection, objec if (Debugger.IsAttached) Trace.WriteLine(String.Format("RecordCount<{0}>: {1}", currenttype, sb)); - - return connection.ExecuteScalarAsync(sb.ToString(), whereConditions, transaction, commandTimeout); + return sb; } } } diff --git a/Dapper.SimpleCRUDTests/Tests.cs b/Dapper.SimpleCRUDTests/Tests.cs index e01d033..2388a8a 100644 --- a/Dapper.SimpleCRUDTests/Tests.cs +++ b/Dapper.SimpleCRUDTests/Tests.cs @@ -1,11 +1,10 @@ -using System.ComponentModel; -using System.Data; +using System.Data; using System.Data.SqlClient; -using System.Diagnostics; using System.Linq; using System.Collections.Generic; using System; using System.Data.SQLite; +using System.Threading.Tasks; using MySql.Data.MySqlClient; using Npgsql; using IBM.Data.DB2.Core; @@ -768,10 +767,10 @@ public void TestMultiInsertASync() { using (var connection = GetOpenConnection()) { - connection.InsertAsync(new User { Name = "TestMultiInsertASync1", Age = 10 }); - connection.InsertAsync(new User { Name = "TestMultiInsertASync2", Age = 10 }); - connection.InsertAsync(new User { Name = "TestMultiInsertASync3", Age = 10 }); - connection.InsertAsync(new User { Name = "TestMultiInsertASync4", Age = 11 }); + connection.InsertAsync(new User { Name = "TestMultiInsertASync1", Age = 10 }, null, null); + connection.InsertAsync(new User { Name = "TestMultiInsertASync2", Age = 10 }, null, null); + connection.InsertAsync(new User { Name = "TestMultiInsertASync3", Age = 10 }, null, null); + connection.InsertAsync(new User { Name = "TestMultiInsertASync4", Age = 11 }, null, null); System.Threading.Thread.Sleep(300); //tiny wait to let the inserts happen var list = connection.GetList(new { Age = 10 }); @@ -785,10 +784,10 @@ public async void MultiInsertWithGuidAsync() { using (var connection = GetOpenConnection()) { - await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }); - await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }); - await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }); - await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }); + await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }, null, null); + await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }, null, null); + await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }, null, null); + await connection.InsertAsync(new GUIDTest { Name = "MultiInsertWithGuidAsync" }, null, null); //tiny wait to let the inserts happen System.Threading.Thread.Sleep(300); var list = connection.GetList(new { Name = "MultiInsertWithGuidAsync" }); @@ -802,7 +801,7 @@ public void TestSimpleGetAsync() using (var connection = GetOpenConnection()) { var id = connection.Insert(new User { Name = "TestSimpleGetAsync", Age = 10 }); - var user = connection.GetAsync(id); + var user = connection.GetAsync(id, null, null); user.Result.Name.IsEqualTo("TestSimpleGetAsync"); connection.Delete(id); } @@ -814,19 +813,19 @@ public void TestMultipleKeyGetAsync() { var keyMaster = new KeyMaster { Key1 = 1, Key2 = 2 }; connection.Insert(keyMaster); - var result = connection.GetAsync(new { Key1 = 1, Key2 = 2 }); + var result = connection.GetAsync(new { Key1 = 1, Key2 = 2 }, null, null); result.Result.Key1.IsEqualTo(1); result.Result.Key2.IsEqualTo(2); connection.Delete(keyMaster); } } - public async void TestDeleteByIdAsync() + public async Task TestDeleteByIdAsync() { using (var connection = GetOpenConnection()) { var id = connection.Insert(new User { Name = "UserAsyncDelete", Age = 10 }); - await connection.DeleteAsync(id); + await connection.DeleteAsync(id, null, null); //tiny wait to let the delete happen connection.Get(id).IsNull(); } @@ -838,7 +837,7 @@ public void TestDeleteByObjectAsync() { var id = connection.Insert(new User { Name = "TestDeleteByObjectAsync", Age = 10 }); var user = connection.Get(id); - connection.DeleteAsync(user); + connection.DeleteAsync(user, null, null); connection.Get(id).IsNull(); connection.Delete(id); } @@ -863,7 +862,7 @@ public void TestSimpleGetListAsync() { connection.Insert(new User { Name = "TestSimpleGetListAsync1", Age = 10 }); connection.Insert(new User { Name = "TestSimpleGetListAsync2", Age = 10 }); - var user = connection.GetListAsync(new { }); + var user = connection.GetListAsync(new { }, null, null); user.Result.Count().IsEqualTo(2); connection.Execute("Delete from Users"); } @@ -878,7 +877,7 @@ public void TestFilteredGetListAsync() connection.Insert(new User { Name = "TestFilteredGetListAsync3", Age = 10 }); connection.Insert(new User { Name = "TestFilteredGetListAsync4", Age = 11 }); - var user = connection.GetListAsync(new { Age = 10 }); + var user = connection.GetListAsync(new { Age = 10 }, null, null); user.Result.Count().IsEqualTo(3); connection.Execute("Delete from Users"); } @@ -893,7 +892,7 @@ public void TestFilteredGetListParametersAsync() connection.Insert(new User { Name = "TestFilteredGetListParametersAsync3", Age = 10 }); connection.Insert(new User { Name = "TestFilteredGetListParametersAsync4", Age = 11 }); - var user = connection.GetListAsync("where Age = @Age", new { Age = 10 }); + var user = connection.GetListAsync("where Age = @Age", new { Age = 10 }, null, null); user.Result.Count().IsEqualTo(3); connection.Execute("Delete from Users"); } @@ -912,9 +911,9 @@ public void TestRecordCountAsync() var resultlist = connection.GetList(); resultlist.Count().IsEqualTo(30); - connection.RecordCountAsync().Result.IsEqualTo(30); + connection.RecordCountAsync("", (object)null, null, null).Result.IsEqualTo(30); - connection.RecordCountAsync("where age = 10 or age = 11").Result.IsEqualTo(2); + connection.RecordCountAsync("where age = 10 or age = 11", (object)null, null, null).Result.IsEqualTo(2); connection.Execute("Delete from Users"); @@ -935,9 +934,9 @@ public void TestRecordCountByObjectAsync() var resultlist = connection.GetList(); resultlist.Count().IsEqualTo(30); - connection.RecordCountAsync().Result.IsEqualTo(30); + connection.RecordCountAsync("", (object)null, null, null).Result.IsEqualTo(30); - connection.RecordCountAsync(new { age = 10 }).Result.IsEqualTo(1); + connection.RecordCountAsync(new { age = 10 }, null, null).Result.IsEqualTo(1); connection.Execute("Delete from Users"); @@ -949,22 +948,22 @@ public void TestInsertWithSpecifiedPrimaryKeyAsync() { using (var connection = GetOpenConnection()) { - var id = connection.InsertAsync(new UserWithoutAutoIdentity() { Id = 999, Name = "User999Async", Age = 10 }); + var id = connection.InsertAsync(new UserWithoutAutoIdentity() { Id = 999, Name = "User999Async", Age = 10 }, null, null); id.Result.IsEqualTo(999); - var user = connection.GetAsync(999); + var user = connection.GetAsync(999, null, null); user.Result.Name.IsEqualTo("User999Async"); connection.Execute("Delete from UserWithoutAutoIdentity"); } } - public async void TestInsertWithMultiplePrimaryKeysAsync() + public async Task TestInsertWithMultiplePrimaryKeysAsync() { using (var connection = GetOpenConnection()) { var keyMaster = new KeyMaster { Key1 = 1, Key2 = 2 }; - await connection.InsertAsync(keyMaster); - var result = connection.GetAsync(new { Key1 = 1, Key2 = 2 }); + await connection.InsertAsync(keyMaster, null, null); + var result = connection.GetAsync(new { Key1 = 1, Key2 = 2 }, null, null); result.Result.Key1.IsEqualTo(1); result.Result.Key2.IsEqualTo(2); connection.Execute("Delete from KeyMaster"); @@ -978,7 +977,7 @@ public void TestInsertUsingGenericLimitedFieldsAsync() var user = new User { Name = "User1", Age = 10, ScheduledDayOff = DayOfWeek.Friday }; //act - var idTask = connection.InsertAsync(user); + var idTask = connection.InsertAsync(user, null, null); idTask.Wait(); var id = idTask.Result; @@ -1345,7 +1344,7 @@ public void TestInsertUsingInterface() } } - public async void TestInsertAsyncUsingInterface() + public async Task TestInsertAsyncUsingInterface() { using (var connection = GetOpenConnection()) using (var transaction = connection.BeginTransaction()) @@ -1358,14 +1357,269 @@ public async void TestInsertAsyncUsingInterface() CreatedDate = new DateTime(2000, 1, 1) }; - await connection.InsertAsync(newUser, transaction); - + await connection.InsertAsync(newUser, transaction, null); + var user = connection.GetList(new { Name = "Jonathan Larouche" }, transaction).FirstOrDefault(); user.Age.IsEqualTo(40); } } + public async Task TestInsertAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + // Test that cancellation token parameter is accepted and method completes successfully + using (var cts = new System.Threading.CancellationTokenSource()) + { + var user = new User { Name = "TestInsertAsyncWithCancellationToken", Age = 25 }; + + // Test the simple InsertAsync method with cancellation token + var id = await connection.InsertAsync(user, token: cts.Token); + id.HasValue.IsTrue(); + + // Verify the user was inserted + var insertedUser = connection.Get(id); + insertedUser.Name.IsEqualTo("TestInsertAsyncWithCancellationToken"); + insertedUser.Age.IsEqualTo(25); + + // Clean up + connection.Delete(id); + } + } + } + + public async Task TestInsertAsyncGenericWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + // Test that cancellation token parameter is accepted for generic InsertAsync method + using (var cts = new System.Threading.CancellationTokenSource()) + { + var car = new Car { Make = "Toyota", Model = "Camry" }; + + // Test the generic InsertAsync method with cancellation token + var id = await connection.InsertAsync(car, token: cts.Token); + (id > 0).IsEqualTo(true); + + // Verify the car was inserted + var insertedCar = connection.Get(id); + insertedCar.Make.IsEqualTo("Toyota"); + insertedCar.Model.IsEqualTo("Camry"); + + // Clean up + connection.Delete(id); + } + } + } + + public async Task TestGetAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + var id = connection.Insert(new User { Name = "TestGetAsyncWithCancellationToken", Age = 30 }); + + // Test GetAsync with cancellation token using new overload + var user = await connection.GetAsync(id, null, null, cts.Token); + user.Name.IsEqualTo("TestGetAsyncWithCancellationToken"); + user.Age.IsEqualTo(30); + + connection.Delete(id); + } + } + } + + public async Task TestGetListAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + connection.Insert(new User { Name = "TestGetListAsync1", Age = 35 }); + connection.Insert(new User { Name = "TestGetListAsync2", Age = 35 }); + + // Test GetListAsync with object conditions and cancellation token using new overload + var users = await connection.GetListAsync(new { Age = 35 }, null, null, cts.Token); + users.Count().IsEqualTo(2); + + // Test GetListAsync with string conditions and cancellation token + var users2 = await connection.GetListAsync("where Age = @Age", new { Age = 35 }, token: cts.Token); + users2.Count().IsEqualTo(2); + + // Test GetListAsync with no conditions - use original method for now + var allUsers = await connection.GetListAsync(); + (allUsers.Count() >= 2).IsEqualTo(true); + + connection.Execute("Delete from Users where Age = 35"); + } + } + } + + public async Task TestGetListPagedAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + // Insert test data + for (int i = 1; i <= 10; i++) + { + connection.Insert(new User { Name = $"TestPaged{i}", Age = 40 + i }); + } + + // Test GetListPagedAsync with cancellation token + var pagedUsers = await connection.GetListPagedAsync(1, 5, "where Age > @MinAge", "Age", new { MinAge = 40 }, token: cts.Token); + pagedUsers.Count().IsEqualTo(5); + + connection.Execute("Delete from Users where Name like 'TestPaged%'"); + } + } + } + + public async Task TestUpdateAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + var id = connection.Insert(new User { Name = "TestUpdateAsync", Age = 40 }); + var user = connection.Get(id); + user.Age = 41; + + // Test UpdateAsync with cancellation token + var rowsAffected = await connection.UpdateAsync(user, token: cts.Token); + rowsAffected.IsEqualTo(1); + + var updatedUser = connection.Get(id); + updatedUser.Age.IsEqualTo(41); + + connection.Delete(id); + } + } + } + + public async Task TestDeleteAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + var id = connection.Insert(new User { Name = "TestDeleteAsync", Age = 45 }); + var user = connection.Get(id); + + // Test DeleteAsync with entity and cancellation token + var rowsAffected = await connection.DeleteAsync(user, token: cts.Token); + rowsAffected.IsEqualTo(1); + + var deletedUser = connection.Get(id); + deletedUser.IsNull(); + } + } + } + + public async Task TestDeleteAsyncByIdWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + var id = connection.Insert(new User { Name = "TestDeleteAsyncById", Age = 50 }); + + // Test DeleteAsync with id and cancellation token + var rowsAffected = await connection.DeleteAsync(id, token: cts.Token); + rowsAffected.IsEqualTo(1); + + var deletedUser = connection.Get(id); + deletedUser.IsNull(); + } + } + } + + public async Task TestDeleteListAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + connection.Insert(new User { Name = "TestDeleteList1", Age = 55 }); + connection.Insert(new User { Name = "TestDeleteList2", Age = 55 }); + connection.Insert(new User { Name = "TestDeleteList3", Age = 56 }); + + // Test DeleteListAsync with object conditions and cancellation token + var rowsAffected = await connection.DeleteListAsync(new { Age = 55 }, token: cts.Token); + rowsAffected.IsEqualTo(2); + + var remainingUsers = connection.GetList(new { Age = 55 }); + remainingUsers.Count().IsEqualTo(0); + + // Clean up remaining test data + connection.Execute("Delete from Users where Age = 56"); + } + } + } + + public async Task TestDeleteListAsyncWithStringConditionsAndCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + connection.Insert(new User { Name = "TestDeleteString1", Age = 57 }); + connection.Insert(new User { Name = "TestDeleteString2", Age = 57 }); + + // Test DeleteListAsync with string conditions and cancellation token + var rowsAffected = await connection.DeleteListAsync("where Age = @Age", new { Age = 57 }, token: cts.Token); + rowsAffected.IsEqualTo(2); + + var remainingUsers = connection.GetList(new { Age = 57 }); + remainingUsers.Count().IsEqualTo(0); + } + } + } + + public async Task TestRecordCountAsyncWithCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + connection.Insert(new User { Name = "TestRecordCount1", Age = 60 }); + connection.Insert(new User { Name = "TestRecordCount2", Age = 60 }); + connection.Insert(new User { Name = "TestRecordCount3", Age = 61 }); + + // Test RecordCountAsync with string conditions and cancellation token + var count1 = await connection.RecordCountAsync("where Age = @Age", new { Age = 60 }, token: cts.Token); + count1.IsEqualTo(2); + + // Test RecordCountAsync with no conditions and cancellation token + var totalCount = await connection.RecordCountAsync(token: cts.Token); + (totalCount >= 3).IsEqualTo(true); + + connection.Execute("Delete from Users where Age in (60, 61)"); + } + } + } + + public async Task TestRecordCountAsyncWithObjectConditionsAndCancellationToken() + { + using (var connection = GetOpenConnection()) + { + using (var cts = new System.Threading.CancellationTokenSource()) + { + connection.Insert(new User { Name = "TestRecordCountObj1", Age = 62 }); + connection.Insert(new User { Name = "TestRecordCountObj2", Age = 62 }); + + // Test RecordCountAsync with object conditions and cancellation token + var count = await connection.RecordCountAsync(new { Age = 62 }, token: cts.Token); + count.IsEqualTo(2); + + connection.Execute("Delete from Users where Age = 62"); + } + } + } + public void TestUpdateUsingInterface() { using (var connection = GetOpenConnection()) @@ -1401,7 +1655,7 @@ public void TestUpdateUsingInterface() } } - public async void TestUpdateAsyncUsingInterface() + public async Task TestUpdateAsyncUsingInterface() { using (var connection = GetOpenConnection()) using (var transaction = connection.BeginTransaction())