We use the following code to commit multiple DTO changes in a single transaction from a smart client application. Users can make many changes including creates, updates and deletes before hitting the Save button which then sends everything to the database. For example, we commit by calling conn.SaveDTOs(clients, orders, invoices);
the code processes deletes from the last parameter to the first one and insert/updates from the first to the last to comply with FK relationships.
Our BaseDTO
has a property to flag changes. It is the base type for DTOs generated from our database with a t4 template.
public static void SaveDTOs(this IDbConnection db, params IEnumerable<BaseDTO>[] dtoList)
{
using (var tran = db.OpenTransaction())
{
//First Delete in reverse for FK constraints
for (int i = dtoList.Length - 1; i >= 0; i--)
foreach (var dto in dtoList[i])
if (dto.UpdateMode == EUpdateMode.Delete)
db.Delete(dto);
//Then Insert and Update in sequence
foreach (var dtos in dtoList)
foreach (var dto in dtos)
{
if (dto.UpdateMode == EUpdateMode.Insert)
db.Insert(dto);
else if (dto.UpdateMode == EUpdateMode.Modify)
db.Update(dto);
}
//Commit the transaction
tran.Commit();
}
}
This worked well in the ServiceStack.OrmLite v3 and fails after we recently bought & upgraded to the commercial version. v3 code used below line to determine the model definition.
var modelDef = objWithProperties.GetType().GetModelDefinition();
It fails in the new versions where modelDef is based on TypeOf(T)
(the boxed BaseDTO
type in this case) instead of the actual object type.
Is there a way to achieve above save logic without duplicating and moving the logic and transaction up to calling code? Is there a better way to achieve the same outcome?
Changing the calling code to below is not nearly as tidy as the original conn.SaveDTOs(clients, orders, invoices);
using (var tran = conn.OpenTransaction())
{
conn.ProcessDTODeletes(invoices);
conn.ProcessDTODeletes(orders);
conn.ProcessDTODeletes(customers);
conn.ProcessDTOInsertAndUpdates(customers);
conn.ProcessDTOInsertAndUpdates(orders);
conn.ProcessDTOInsertAndUpdates(invoices);
}
Thanks for your assistance,
Carl