internal static int SaveAll <T>(this IDbCommand dbCmd, IEnumerable <T> objs) { var saveRows = objs.ToList(); var firstRow = saveRows.FirstOrDefault(); if (Equals(firstRow, default(T))) { return(0); } var modelDef = typeof(T).GetModelDefinition(); var firstRowId = modelDef.GetPrimaryKey(firstRow); var defaultIdValue = firstRowId?.GetType().GetDefaultValue(); var idMap = defaultIdValue != null ? saveRows.Where(x => !defaultIdValue.Equals(modelDef.GetPrimaryKey(x))).ToSafeDictionary(x => modelDef.GetPrimaryKey(x)) : saveRows.Where(x => modelDef.GetPrimaryKey(x) != null).ToSafeDictionary(x => modelDef.GetPrimaryKey(x)); var existingRowsMap = dbCmd.SelectByIds <T>(idMap.Keys).ToDictionary(x => modelDef.GetPrimaryKey(x)); var rowsAdded = 0; IDbTransaction dbTrans = null; if (dbCmd.Transaction == null) { dbCmd.Transaction = dbTrans = dbCmd.Connection.BeginTransaction(); } try { var dialect = dbCmd.Dialect(); foreach (var row in saveRows) { var id = modelDef.GetPrimaryKey(row); if (id != defaultIdValue && existingRowsMap.ContainsKey(id)) { dbCmd.Update(row); } else { if (modelDef.HasAutoIncrementId) { var newId = dbCmd.Insert(row, commandFilter: null, selectIdentity: true); var safeId = dialect.FromDbValue(newId, modelDef.PrimaryKey.FieldType); modelDef.PrimaryKey.SetValue(row, safeId); id = newId; } else { dbCmd.Insert(row, commandFilter: null); } rowsAdded++; } modelDef.RowVersion?.SetValue(row, dbCmd.GetRowVersion(modelDef, id)); } dbTrans?.Commit(); } finally { dbTrans?.Dispose(); if (dbCmd.Transaction == dbTrans) { dbCmd.Transaction = null; } } return(rowsAdded); }