public List <SqlDataRecord> ConvertListParameterValue(object value, SqlListParamPlaceHolder lph) { var list = value as IList; if (list == null || list.Count == 0) { return(null); //it should null, not DbNull.Value } bool isEnum = lph.ElementType.IsEnum; var records = new List <SqlDataRecord>(); var rowMetaData = new SqlMetaData("Value", SqlDbType.Variant); foreach (object elem in list) { var rec = new SqlDataRecord(rowMetaData); var v1 = isEnum ? ConvertHelper.EnumValueToInt(elem, lph.ElementType) : elem; rec.SetValue(0, v1); records.Add(rec); } if (records.Count == 0) { return(null); // with 0 rows throws error, advising to send NULL } return(records); }
protected virtual SqlPlaceHolder CreateSqlPlaceHolder(ExternalValueExpression extValue) { var dataType = extValue.SourceExpression.Type; var driver = this.DbModel.Driver; var typeRegistry = driver.TypeRegistry; var valueReader = BuildParameterValueReader(extValue.SourceExpression); SqlPlaceHolder ph; if (dataType.IsListOfDbPrimitive(out var elemType)) { // list parameter var elemTypeDef = typeRegistry.GetDbTypeDef(elemType); Util.Check(elemTypeDef != null, "Failed to match DB type for CLR type {0}", elemType); ph = new SqlListParamPlaceHolder(elemType, elemTypeDef, valueReader, // ToLiteral formatLiteral: list => driver.SqlDialect.ListToLiteral(list, elemTypeDef) ); } else { //regular linq parameter var typeDef = typeRegistry.GetDbTypeDef(dataType); Util.Check(typeDef != null, "Failed to find DB type for linq parameter of type {0}", dataType); var dbConv = typeRegistry.GetDbValueConverter(typeDef.ColumnOutType, dataType); Util.Check(dbConv != null, "Failed to find converter from type {0} to type {1}", dataType, typeDef.ColumnOutType); ph = new SqlLinqParamPlaceHolder(dataType, valueReader, dbConv.PropertyToColumn, typeDef.ToLiteral); } this.PlaceHolders.Add(ph); return(ph); }
private string FormatListPlaceHolder(SqlListParamPlaceHolder ph, object arg) { // read value from locals (linq); for DeleteMany: read list of IDs from list of records var list = ph.ListValueReader((object[])arg); // always use parameter, unless option is not available var useLiteral = !_driver.Supports(DbFeatures.ArrayParameters) || _genMode == SqlGenMode.NoParameters; if (useLiteral) { return(ph.FormatLiteral(list)); } else { var prm = _sqlDialect.AddDbParameter(_dbCommand, ph, list); var fmt = ph.FormatParameter; return(fmt == null ? prm.ParameterName : fmt(prm)); } }
public virtual SqlStatement BuildCrudDeleteMany(DbTableInfo table) { var pk = table.PrimaryKey; Util.Check(pk.KeyColumns.Count == 1, "Fatal: cannot use DeleteMany for table with composite PK."); var pkCol = pk.KeyColumns[0].Column; var elemTypeDef = pkCol.TypeInfo.TypeDef; var pkListPh = new SqlListParamPlaceHolder(pkCol.Member.DataType, elemTypeDef, // Placeholder expects here function that reads the value from local environment; // we provide a function that will take List<EntityRecord> and produce list of PK values valueReader: recs => GetPrimaryKeyValues(recs, table), // ToLiteral formatLiteral: list => DbModel.Driver.SqlDialect.ListToLiteral(list, elemTypeDef) ); var placeHolders = new SqlPlaceHolderList(); placeHolders.Add(pkListPh); var sql = SqlDialect.SqlCrudTemplateDeleteMany.Format(table.SqlFullName, pkCol.SqlColumnNameQuoted, pkListPh); var stmt = new SqlStatement(SqlKind.DeleteMany, sql, placeHolders, DbExecutionType.NonQuery); return(stmt); }