NPoco (a .NET micro ORM, derived from PetaPoco) has a method for bulk-inserting records into a database, given a list of a generic type. The method signature is:
void InsertBulk<T>(IEnumerable<T> pocos);
Internally it takes the name of the type T and uses it to determine the DB table to insert into (similarly the type's property names are mapped to the column names). Therefore it is critically important that a variable of the correct type is passed to the method.
My challenge is this:
List<IDataItem>
where IDataItem is an interface that all insertable objects' classes must implementI have tried the following approach, but the result of Convert.ChangeType is Object, so I am passing a list of Objects to InsertBulk, which is invalid.
private static Exception SaveDataItemsToDatabase(List<IDataItem> dtos)
{
using (var db = new DbConnection())
{
try
{
var dtosByType = dtos.GroupBy(x => x.GetType());
db.Data.BeginTransaction();
foreach (var dataType in dtosByType)
{
var type = dataType.Key;
var dtosOfType = dataType.Select(x => Convert.ChangeType(x, type));
db.Data.InsertBulk(dtosOfType);
}
db.Data.CommitTransaction();
return null;
}
catch (Exception ex)
{
db.Data.RollbackTransaction();
return ex;
}
}
}
Is there any way I can accomplish this?
You have to create a new list of type List<T>
and copy all your items to it, then call InsertBulk
via reflection.
foreach(var g in groups)
{
var dataItemType = g.Key;
var listType = typeof(List<>).MakeGenericType(new [] { dataItemType });
var list = (IList) Activator.CreateInstance(listType);
foreach(var data in g)
list.Add(data);
db.Data.GetType()
.GetMethod("InsertBulk")
.MakeGenericMethod(dataItemType)
.Invoke(db.Data, new object[] { list });
}
See it working here: https://dotnetfiddle.net/BS2FLy