Skip to content

Commit bf087b1

Browse files
authored
Merge pull request #193 from jonathanlarouche/master
Allowing Interface variable reference to be used for Update & Insert
2 parents c00e767 + a928c36 commit bf087b1

File tree

4 files changed

+178
-10
lines changed

4 files changed

+178
-10
lines changed

Dapper.SimpleCRUD/SimpleCRUD.cs

+14
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,13 @@ public static IEnumerable<T> GetListPaged<T>(this IDbConnection connection, int
350350
/// <returns>The ID (primary key) of the newly inserted record if it is identity using the defined type, otherwise null</returns>
351351
public static TKey Insert<TKey, TEntity>(this IDbConnection connection, TEntity entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null)
352352
{
353+
if (typeof(TEntity).IsInterface) //FallBack to BaseType Generic Method : https://stackoverflow.com/questions/4101784/calling-a-generic-method-with-a-dynamic-type
354+
{
355+
return (TKey)typeof(SimpleCRUD)
356+
.GetMethods().Where(methodInfo=>methodInfo.Name == nameof(Insert) && methodInfo.GetGenericArguments().Count()==2).Single()
357+
.MakeGenericMethod(new Type[] { typeof(TKey), entityToInsert.GetType() })
358+
.Invoke(null, new object[] { connection,entityToInsert,transaction,commandTimeout });
359+
}
353360
var idProps = GetIdProperties(entityToInsert).ToList();
354361

355362
if (!idProps.Any())
@@ -427,6 +434,13 @@ public static TKey Insert<TKey, TEntity>(this IDbConnection connection, TEntity
427434
/// <returns>The number of affected records</returns>
428435
public static int Update<TEntity>(this IDbConnection connection, TEntity entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null)
429436
{
437+
if (typeof(TEntity).IsInterface) //FallBack to BaseType Generic Method: https://stackoverflow.com/questions/4101784/calling-a-generic-method-with-a-dynamic-type
438+
{
439+
return (int)typeof(SimpleCRUD)
440+
.GetMethods().Where(methodInfo => methodInfo.Name == nameof(Update) && methodInfo.GetGenericArguments().Count() == 1).Single()
441+
.MakeGenericMethod(new Type[] { entityToUpdate.GetType() })
442+
.Invoke(null, new object[] { connection, entityToUpdate, transaction, commandTimeout });
443+
}
430444
var masterSb = new StringBuilder();
431445
StringBuilderCache(masterSb, $"{typeof(TEntity).FullName}_Update", sb =>
432446
{

Dapper.SimpleCRUD/SimpleCRUDAsync.cs

+16-2
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@ public static Task<IEnumerable<T>> GetListPagedAsync<T>(this IDbConnection conne
236236
/// <returns>The ID (primary key) of the newly inserted record if it is identity using the defined type, otherwise null</returns>
237237
public static async Task<TKey> InsertAsync<TKey, TEntity>(this IDbConnection connection, TEntity entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null)
238238
{
239+
if (typeof(TEntity).IsInterface) //FallBack to BaseType Generic Method : https://stackoverflow.com/questions/4101784/calling-a-generic-method-with-a-dynamic-type
240+
{
241+
return await (Task<TKey>)typeof(SimpleCRUD)
242+
.GetMethods().Where(methodInfo => methodInfo.Name == nameof(InsertAsync) && methodInfo.GetGenericArguments().Count() == 2).Single()
243+
.MakeGenericMethod(new Type[] { typeof(TKey), entityToInsert.GetType() })
244+
.Invoke(null, new object[] { connection, entityToInsert, transaction, commandTimeout });
245+
}
239246
var idProps = GetIdProperties(entityToInsert).ToList();
240247

241248
if (!idProps.Any())
@@ -310,8 +317,15 @@ public static async Task<TKey> InsertAsync<TKey, TEntity>(this IDbConnection con
310317
/// <param name="transaction"></param>
311318
/// <param name="commandTimeout"></param>
312319
/// <returns>The number of affected records</returns>
313-
public static Task<int> UpdateAsync<TEntity>(this IDbConnection connection, TEntity entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null, System.Threading.CancellationToken? token = null)
320+
public static async Task<int> UpdateAsync<TEntity>(this IDbConnection connection, TEntity entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null, System.Threading.CancellationToken? token = null)
314321
{
322+
if (typeof(TEntity).IsInterface) //FallBack to BaseType Generic Method : https://stackoverflow.com/questions/4101784/calling-a-generic-method-with-a-dynamic-type
323+
{
324+
return await(Task<int>)typeof(SimpleCRUD)
325+
.GetMethods().Where(methodInfo => methodInfo.Name == nameof(UpdateAsync) && methodInfo.GetGenericArguments().Count() == 1).Single()
326+
.MakeGenericMethod(new Type[] { entityToUpdate.GetType() })
327+
.Invoke(null, new object[] { connection, entityToUpdate, transaction, commandTimeout, token });
328+
}
315329
var idProps = GetIdProperties(entityToUpdate).ToList();
316330

317331
if (!idProps.Any())
@@ -331,7 +345,7 @@ public static Task<int> UpdateAsync<TEntity>(this IDbConnection connection, TEnt
331345
Trace.WriteLine(String.Format("Update: {0}", sb));
332346

333347
System.Threading.CancellationToken cancelToken = token ?? default(System.Threading.CancellationToken);
334-
return connection.ExecuteAsync(new CommandDefinition(sb.ToString(), entityToUpdate, transaction, commandTimeout, cancellationToken: cancelToken));
348+
return await connection.ExecuteAsync(new CommandDefinition(sb.ToString(), entityToUpdate, transaction, commandTimeout, cancellationToken: cancelToken));
335349
}
336350

337351
/// <summary>

Dapper.SimpleCRUDTests/Program.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace Dapper.SimpleCRUDTests
1212
{
1313
class Program
1414
{
15+
public const string SQLServerName = @".\sqlexpress";
16+
1517
static void Main()
1618
{
1719
//Setup();
@@ -38,7 +40,7 @@ static void Main()
3840

3941
private static void Setup()
4042
{
41-
using (var connection = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=Master;Integrated Security=True"))
43+
using (var connection = new SqlConnection($@"Data Source={SQLServerName};Initial Catalog=Master;Integrated Security=True"))
4244
{
4345
connection.Open();
4446
try
@@ -51,7 +53,7 @@ private static void Setup()
5153
connection.Execute(@" CREATE DATABASE DapperSimpleCrudTestDb; ");
5254
}
5355

54-
using (var connection = new SqlConnection(@"Data Source = .\sqlexpress;Initial Catalog=DapperSimpleCrudTestDb;Integrated Security=True"))
56+
using (var connection = new SqlConnection($@"Data Source ={SQLServerName};Initial Catalog=DapperSimpleCrudTestDb;Integrated Security=True"))
5557
{
5658
connection.Open();
5759
connection.Execute(@" create table Users (Id int IDENTITY(1,1) not null, Name nvarchar(100) not null, Age int not null, ScheduledDayOff int null, CreatedDate datetime DEFAULT(getdate())) ");
@@ -170,7 +172,7 @@ private static void RunTests()
170172
// Write result
171173
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
172174

173-
using (var connection = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=Master;Integrated Security=True"))
175+
using (var connection = new SqlConnection($@"Data Source={SQLServerName};Initial Catalog=Master;Integrated Security=True"))
174176
{
175177
connection.Open();
176178
try

Dapper.SimpleCRUDTests/Tests.cs

+143-5
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,23 @@ public class City
102102
public int Population { get; set; }
103103
}
104104

105+
public interface INameColumn
106+
{
107+
string Name { get; set; }
108+
}
109+
110+
[Table("City")]
111+
public class CityWithIName : City, INameColumn
112+
{
113+
114+
}
115+
116+
[Table("Users")]
117+
public class UserWithIName : User, INameColumn
118+
{
119+
120+
}
121+
105122
public class GUIDTest
106123
{
107124
[Key]
@@ -198,7 +215,7 @@ private IDbConnection GetOpenConnection()
198215
}
199216
else
200217
{
201-
connection = new SqlConnection(@"Data Source = .\sqlexpress;Initial Catalog=DapperSimpleCrudTestDb;Integrated Security=True;MultipleActiveResultSets=true;");
218+
connection = new SqlConnection($@"Data Source={Program.SQLServerName};Initial Catalog=DapperSimpleCrudTestDb;Integrated Security=True;MultipleActiveResultSets=true;");
202219
SimpleCRUD.SetDialect(SimpleCRUD.Dialect.SQLServer);
203220
}
204221

@@ -220,7 +237,7 @@ public void TestInsertWithSpecifiedTableName()
220237
}
221238
}
222239

223-
public void TestMassInsert()
240+
public void TestMassInsert()
224241
{
225242
//With cached strinb builder, this tests runs 2.5X faster (From 400ms to 180ms)
226243
using (var connection = GetOpenConnection())
@@ -804,14 +821,13 @@ public void TestMultipleKeyGetAsync()
804821
}
805822
}
806823

807-
public void TestDeleteByIdAsync()
824+
public async void TestDeleteByIdAsync()
808825
{
809826
using (var connection = GetOpenConnection())
810827
{
811828
var id = connection.Insert(new User { Name = "UserAsyncDelete", Age = 10 });
812-
connection.DeleteAsync<User>(id);
829+
await connection.DeleteAsync<User>(id);
813830
//tiny wait to let the delete happen
814-
System.Threading.Thread.Sleep(300);
815831
connection.Get<User>(id).IsNull();
816832
}
817833
}
@@ -1298,6 +1314,128 @@ public void TestGetListNullableWhere()
12981314
}
12991315
}
13001316

1317+
public void TestInsertUsingInterface()
1318+
{
1319+
using (var connection = GetOpenConnection())
1320+
using (var transaction = connection.BeginTransaction())
1321+
{
1322+
INameColumn newUser = new UserWithIName
1323+
{
1324+
Age = 40,
1325+
Name = "Jonathan Larouche",
1326+
ScheduledDayOff = DayOfWeek.Sunday,
1327+
CreatedDate = new DateTime(2000, 1, 1)
1328+
};
1329+
1330+
connection.Insert(newUser, transaction);
1331+
1332+
INameColumn newCity = new CityWithIName
1333+
{
1334+
Name = "Montreal",
1335+
Population = 5675
1336+
};
1337+
1338+
connection.Insert<string, INameColumn>(newCity, transaction);
1339+
1340+
var user = connection.GetList<UserWithIName>(new { Name = "Jonathan Larouche" }, transaction).FirstOrDefault();
1341+
user.Age.IsEqualTo(40);
1342+
var city = connection.GetList<CityWithIName>(new { Name = "Montreal" }, transaction).FirstOrDefault();
1343+
city.Population.IsEqualTo(5675);
1344+
1345+
}
1346+
}
1347+
1348+
public async void TestInsertAsyncUsingInterface()
1349+
{
1350+
using (var connection = GetOpenConnection())
1351+
using (var transaction = connection.BeginTransaction())
1352+
{
1353+
INameColumn newUser = new UserWithIName
1354+
{
1355+
Age = 40,
1356+
Name = "Jonathan Larouche",
1357+
ScheduledDayOff = DayOfWeek.Sunday,
1358+
CreatedDate = new DateTime(2000, 1, 1)
1359+
};
1360+
1361+
await connection.InsertAsync(newUser, transaction);
1362+
1363+
var user = connection.GetList<UserWithIName>(new { Name = "Jonathan Larouche" }, transaction).FirstOrDefault();
1364+
user.Age.IsEqualTo(40);
1365+
1366+
}
1367+
}
1368+
1369+
public void TestUpdateUsingInterface()
1370+
{
1371+
using (var connection = GetOpenConnection())
1372+
using (var transaction = connection.BeginTransaction())
1373+
{
1374+
INameColumn newUser = new UserWithIName
1375+
{
1376+
Age = 40,
1377+
Name = "Jonathan Larouche",
1378+
ScheduledDayOff = DayOfWeek.Sunday,
1379+
CreatedDate = new DateTime(2000, 1, 1)
1380+
};
1381+
1382+
((UserWithIName)newUser).Id = connection.Insert(newUser, transaction).Value;
1383+
((UserWithIName)newUser).Age = 41;
1384+
connection.Update(newUser, transaction);
1385+
1386+
INameColumn newCity = new CityWithIName
1387+
{
1388+
Name = "Montreal",
1389+
Population = 5675
1390+
};
1391+
1392+
connection.Insert<string, INameColumn>(newCity, transaction);
1393+
((CityWithIName)newCity).Population = 6000;
1394+
connection.Update(newCity, transaction);
1395+
1396+
var user = connection.GetList<UserWithIName>(new { Name = "Jonathan Larouche" }, transaction).FirstOrDefault();
1397+
user.Age.IsEqualTo(41);
1398+
var city = connection.GetList<CityWithIName>(new { Name = "Montreal" }, transaction).FirstOrDefault();
1399+
city.Population.IsEqualTo(6000);
1400+
1401+
}
1402+
}
1403+
1404+
public async void TestUpdateAsyncUsingInterface()
1405+
{
1406+
using (var connection = GetOpenConnection())
1407+
using (var transaction = connection.BeginTransaction())
1408+
{
1409+
INameColumn newUser = new UserWithIName
1410+
{
1411+
Age = 40,
1412+
Name = "Jonathan Larouche",
1413+
ScheduledDayOff = DayOfWeek.Sunday,
1414+
CreatedDate = new DateTime(2000, 1, 1)
1415+
};
1416+
1417+
((UserWithIName)newUser).Id = connection.Insert(newUser, transaction).Value;
1418+
((UserWithIName)newUser).Age = 41;
1419+
await connection.UpdateAsync(newUser, transaction);
1420+
1421+
INameColumn newCity = new CityWithIName
1422+
{
1423+
Name = "Montreal",
1424+
Population = 5675
1425+
};
1426+
1427+
connection.Insert<string, INameColumn>(newCity, transaction);
1428+
((CityWithIName)newCity).Population = 6000;
1429+
await connection.UpdateAsync(newCity, transaction);
1430+
1431+
var user = connection.GetList<UserWithIName>(new { Name = "Jonathan Larouche" }, transaction).FirstOrDefault();
1432+
user.Age.IsEqualTo(41);
1433+
var city = connection.GetList<CityWithIName>(new { Name = "Montreal" }, transaction).FirstOrDefault();
1434+
city.Population.IsEqualTo(6000);
1435+
1436+
}
1437+
}
1438+
13011439
//ignore attribute tests
13021440
//i cheated here and stuffed all of these in one test
13031441
//didn't implement in postgres or mysql tests yet

0 commit comments

Comments
 (0)