private static void AddMember(ModelDef modelDef, string memberName, Type type, string requiredNamespace) { string typeCode = type.Name; string typeNamespace = type.Namespace; if (type.Namespace != requiredNamespace) { string vernacularCode = TypeConvertor.ConvertCLRToVernacular(type.ToString()); if (vernacularCode != null) { typeCode = vernacularCode; typeNamespace = null; } } /* TODO: better to use IsClass or IsByRef ? */ bool isReference = type.IsClass || type.IsInterface; if (memberName == "State") { Shared.Info("State"); } if (typeCode == "string") { isReference = false; } /* TODO: not sure if this should rewrite the type here or not */ /* TODO: the Interface rewriting should be an option */ if (type.IsInterface && typeCode.StartsWith("I")) { typeCode = typeCode.Substring(1); } PropertyDef propertyDef = new PropertyDef { PropertyName = memberName, PropertyTypeCode = typeCode, PropertyTypeNamespace = typeNamespace, IsInterface = type.IsInterface, IsReference = isReference, IsEnum = type.IsEnum }; modelDef.PropertyDefMap[memberName] = propertyDef; }
/* TODO: GetSchemaTable was failing on SQL Server Express, not sure why. * It's not that it needed data rows in the table. * Does it need data actually returned? */ private void PopulateFields2008(ProcedureDef procedureDef) { /* MSSQL prior to 2012 might need this, we can verify if there's a client to test against at some point */ /* * call the procedure to see the result set * */ using (SqlTransaction trans = this.SqlConnection.BeginTransaction()) { using (SqlCommand command = new SqlCommand() { CommandText = procedureDef.ProcedureName, CommandType = CommandType.StoredProcedure, Connection = this.SqlConnection, Transaction = trans }) { foreach (ParameterDef parameterDef in procedureDef.ParameterDefMap.Values) { ParameterDirection direction; if (parameterDef.IsOutParameter) { direction = ParameterDirection.Output; } else { direction = ParameterDirection.Input; } var parameter = new SqlParameter { ParameterName = parameterDef.ParameterName, Direction = direction, Size = parameterDef.ParameterSize, SqlDbType = GetSqlDbType(parameterDef.ParameterDataTypeCode) }; parameter.Value = DBNull.Value; command.Parameters.Add(parameter); } DataTable tableSchema; /* we really want all 3 behaviors, and within a transaction, but the two * behaviors CommandBehavior.SchemaOnly and CommandBehavior.KeyInfo fail * to give us a schema table to read. So we have to get a result within * a transaction. There's nothing super wrong with that, but it feels * dirty. Here are the results of combinations we've tried (all with SQL * Server Express 2014): * No behaviors, no transaction : succeeded * CommandBehavior.SchemaOnly alone, no transaction : failed * CommandBehavior.SchemaOnly| CommandBehavior.KeyInfo, no trans : failed * CommandBehavior.SchemaOnly| CommandBehavior.SingleResult, no trans : failed * CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo | CommandBehavior.SingleResult, no trans : failed * CommandBehavior.KeyInfo, no trans : failed * CommandBehavior.KeyInfo | CommandBehavior.SingleResult, no trans : failed * CommandBehavior.SingleResult, no trans : succeeded * No behaviors, with trans : succeeded * CommandBehavior.SingleResult, with trans : succeeded */ using (var reader = command.ExecuteReader(CommandBehavior.SingleResult)) { reader.Read(); tableSchema = reader.GetSchemaTable(); } trans.Rollback(); if (tableSchema == null) { throw new ApplicationException("Sampling of procedure " + procedureDef.ProcedureName + " yielded no schema."); } foreach (DataRow row in tableSchema.Rows) { /* IsIdentity */ /* * int columnSize = (int)row["ColumnSize"]; * string sqlTypeCode = * bool isReadOnly = (bool)row["IsReadOnly"]; * bool isPrimaryKey = (bool)row["IsKey"]; * bool isAutoIncrement = (bool)row["IsAutoIncrement"]; */ string fieldName = row["ColumnName"].ToString(); /* TODO: on views, these BaseTableName and BaseColumnName are for the view, not the source table like we get for MSSQL2012 */ string baseTableName = row["BaseTableName"].ToString(); string baseColumnName = row["BaseColumnName"].ToString(); bool isNullable = (bool)row["AllowDBNull"]; string dataTypeCode = TypeConvertor.ConvertCLRToVernacular(row["DataType"].ToString()); FieldDef fieldDef = new FieldDef { FieldName = fieldName, ProcedureDef = procedureDef, DataTypeCode = dataTypeCode, IsNullable = isNullable, BaseTableName = baseTableName, BaseColumnName = baseColumnName }; procedureDef.FieldDefMap[fieldDef.FieldName] = fieldDef; } } } }