in Backend/src/Trackable.EntityFramework/DbContextBulkOperations.cs [97:175]
private static async Task UpdateAsync(
DbContext context,
string tableName,
IDictionary<string, Type> idFields,
IDictionary<string, Type> fieldsToUpdate,
IEnumerable<List<Object>> rows)
{
var table = new DataTable();
// Id fields are guaranteed to be primitives
foreach (var idField in idFields)
{
table.Columns.Add(idField.Key, idField.Value);
}
var primitiveFields = new Dictionary<string, Type>();
var excludedColumns = new List<int>();
int index = idFields.Count;
foreach (var column in fieldsToUpdate)
{
// DataTable does not support Nullable types, instead primitive types should be added
// and the column marked as AllowDbNull
if (column.Value.IsGenericType && column.Value.GetGenericTypeDefinition() == typeof(Nullable<>))
{
DataColumn col = new DataColumn(column.Key, column.Value.GetGenericArguments().First());
col.AllowDBNull = true;
table.Columns.Add(col);
primitiveFields.Add(column.Key, column.Value.GetGenericArguments().First());
}
else if(SqlTypeHelper.GetDbType(column.Value).HasValue)
{
table.Columns.Add(column.Key, column.Value);
primitiveFields.Add(column.Key, column.Value);
}
else
{
// Column is unsupported type. Do not include it.
excludedColumns.Add(index);
}
index++;
}
excludedColumns.Reverse();
foreach (var row in rows)
{
foreach(var col in excludedColumns)
{
row.RemoveAt(col);
}
table.Rows.Add(row.ToArray());
}
var connectionInitialState = context.Database.Connection.State;
try
{
if (connectionInitialState != ConnectionState.Open)
{
await context.Database.Connection.OpenAsync();
}
var typeName = await ExecuteTypeSqlCommand(context, tableName, idFields, primitiveFields);
var storedProcedureName = await ExecuteStoredProcedureSqlCommand(context, tableName, typeName, idFields, primitiveFields);
await ExecuteUpdateAsync(context, table, storedProcedureName, typeName);
}
finally
{
if (connectionInitialState != ConnectionState.Open)
{
context.Database.Connection.Close();
}
}
}