/// <summary> /// Initializes a new instance of the <see cref="OKHOSTING.ORM.DataMember"/> class. /// <para xml:lang="es"> /// Inicializa una nueva instancia de la clase OKHOSTING.ORM.DataMember /// </para> /// </summary> /// <param name="type">Type. /// <para xml:lang="es">El tipo del dato.</para> /// </param> /// <param name="member">Member. /// <para xml:lang="es">El miembro.</para> /// </param> /// <param name="column">Column. /// <para xml:lang="es">La columna.</para> /// </param> public DataMember(DataType type, string member, Column column) { if (type == null) { throw new ArgumentNullException("type"); } if (string.IsNullOrWhiteSpace(member)) { throw new ArgumentNullException("member"); } DataType = type; Expression = new MemberExpression(type.InnerType, member); if (column == null) { CreateColumn(); } else { if (column.Table != type.Table) { throw new ArgumentOutOfRangeException("column", column, "This column does not belong the the Table that TypeMap is mapped to"); } Column = column; } }
public ColumnValue(Column column, object value) { if (column == null) { throw new ArgumentNullException("column"); } Column = column; Value = value; }
/// <summary> /// Constructs the AggegateSelectField /// </summary> /// <param name="dataValue"> /// DataMember for build the field definition /// </param> /// <param name="alias"> /// Alias name of the resulting field /// </param> public SelectColumn(Column column, string alias) { if (column == null) { throw new ArgumentNullException("column"); } Column = column; Alias = alias; }
/// <summary> /// Returns the full schema of the database including tables, indexes, foreign keys, etc. /// </summary> /// <remarks> /// It's very slow for large databases /// </remarks> public static DataBaseSchema Load(DataBase database, string schemaProvider) { DataBaseSchema schema = new DataBaseSchema(); DatabaseSchema schemaReader; using (var dbReader = new DatabaseSchemaReader.DatabaseReader(database.ConnectionString, schemaProvider)) { dbReader.AllTables(); dbReader.AllViews(); try { dbReader.AllStoredProcedures(); } catch { } try { dbReader.AllUsers(); } catch { } schemaReader = dbReader.DatabaseSchema; } foreach (DatabaseTable dbt in schemaReader.Tables) { if (dbt.PrimaryKeyColumn == null) { continue; } dbt.PrimaryKeyColumn.AddIdentity(); var table = new Table() { Name = dbt.Name, DataBase = schema, IdentityIncrement = dbt.PrimaryKeyColumn.IdentityDefinition.IdentityIncrement, IdentitySeed = dbt.PrimaryKeyColumn.IdentityDefinition.IdentitySeed, }; schema.Tables.Add(table); } foreach (DatabaseTable dbt in schemaReader.Tables) { if (dbt.PrimaryKeyColumn == null) { continue; } var table = schema[dbt.Name]; foreach (DatabaseColumn dbc in dbt.Columns) { Column column = new Column() { Name = dbc.Name, Table = table, Description = dbc.Description, IsNullable = dbc.Nullable, IsAutoNumber = dbc.IsAutoNumber, ComputedDefinition = dbc.ComputedDefinition, DefaultValue = dbc.DefaultValue, IsPrimaryKey = dbc.IsPrimaryKey, Length = (uint?) dbc.Length, Ordinal = dbc.Ordinal, Precision = dbc.Precision, Scale = dbc.Scale, }; if (dbc.DataType != null) { column.DbType = DbTypeMapper.Parse(dbc.DataType.GetNetType()); } else { if(dbc.DbDataType.StartsWith("varchar")) { column.DbType = DbType.AnsiString; } else if (dbc.DbDataType.StartsWith("int")) { column.DbType = DbType.Int32; } else if (dbc.DbDataType.StartsWith("decimal")) { column.DbType = DbType.Decimal; } else if (dbc.DbDataType.StartsWith("datetime")) { column.DbType = DbType.DateTime; } else if (dbc.DbDataType.StartsWith("money")) { column.DbType = DbType.Currency; } else if (dbc.DbDataType.StartsWith("char")) { column.DbType = DbType.AnsiStringFixedLength; } else if (dbc.DbDataType.StartsWith("text")) { column.DbType = DbType.AnsiString; } } table.Columns.Add(column); } foreach (DatabaseIndex dbi in dbt.Indexes) { Index index = new Index() { Name = dbi.Name, Table = table, Direction = SortDirection.Ascending, Unique = dbi.IsUnique, }; foreach (DatabaseColumn dbc in dbi.Columns) { index.Columns.Add(table[dbc.Name]); } table.Indexes.Add(index); } foreach (DatabaseTrigger dbtr in dbt.Triggers) { DataBaseOperation operation = DataBaseOperation.Insert; Enum.TryParse<DataBaseOperation>(dbtr.TriggerEvent, true, out operation); Trigger trigger = new Trigger() { TriggerBody = dbtr.TriggerBody, TriggerEvent = operation, Table = table, }; table.Triggers.Add(trigger); } foreach (DatabaseConstraint dbcons in dbt.CheckConstraints) { if (dbcons.ConstraintType == ConstraintType.Check) { CheckConstraint constraint = new CheckConstraint() { Expression = dbcons.Expression, Table = table, }; table.CheckConstraints.Add(constraint); } else if (dbcons.ConstraintType == ConstraintType.ForeignKey) { ForeignKey foreignKey = new ForeignKey() { Name= dbcons.Name, DeleteAction = schema.ParseConstraintAction(dbcons.DeleteRule), UpdateAction =schema.ParseConstraintAction(dbcons.UpdateRule), RemoteTable = schema[dbcons.RefersToTable], Table = table, }; var referencedColumns = dbcons.ReferencedColumns(schemaReader).ToArray(); for (int i = 0; i < dbcons.Columns.Count; i++) { foreignKey.Columns.Add(new Tuple<Column,Column>(table[dbcons.Columns[i]], foreignKey.RemoteTable[referencedColumns[i]])); } table.ForeignKeys.Add(foreignKey); } } } foreach (DatabaseView dbv in schemaReader.Views) { View view = new View() { Name = dbv.Name, Command = dbv.Sql, Description = dbv.Description, DataBase = schema, }; schema.Views.Add(view); } foreach (DatabaseUser dbu in schemaReader.Users) { User user = new User() { Name = dbu.Name, DataBase = schema, }; schema.Users.Add(user); } return schema; }
/// <summary> /// Creates a list of new DataTypes, creating as well a list of new Tables with all members of type as columns /// </summary> public static IEnumerable<DataType> DefaultMap(IEnumerable<Type> types) { //we will store here all types that are actually persistent List<DataType> persistentTypes = new List<DataType>(); Random random = new Random(); //map primary keys first, so we allow to foreign keys and inheritance to be correctly mapped foreach (Type type in types) { //skip enums and interfaces if (type.GetTypeInfo().IsEnum || type.GetTypeInfo().IsInterface) { continue; } //ignore types with no primary key var pk = GetMappableMembers(type).Where(m => DataMember.IsPrimaryKey(m)); if (pk.Count() == 0) { continue; } DataType dtype = new DataType(type); AllDataTypes.Add(dtype); foreach (var memberInfo in pk) { //create datamember dtype.AddMember(memberInfo.Name); } persistentTypes.Add(dtype); } foreach (DataType dtype in persistentTypes) { //create inheritance foreign keys if (dtype.BaseDataType != null) { ForeignKey foreignKey = new ForeignKey(); foreignKey.Table = dtype.Table; foreignKey.RemoteTable = dtype.BaseDataType.Table; foreignKey.Name = "FK_" + dtype.Name + "_" + dtype.BaseDataType.Name + "_" + random.Next(); //we asume that primary keys on parent and child tables have the same number and order of related columns for (int i = 0; i < dtype.PrimaryKey.Count(); i++) { DataMember pk = dtype.PrimaryKey.ToArray()[i]; DataMember basePk = dtype.BaseDataType.PrimaryKey.ToArray()[i]; foreignKey.Columns.Add(new Tuple<Column, Column>(pk.Column, basePk.Column)); } dtype.Table.ForeignKeys.Add(foreignKey); } //map non primary key members now foreach (var memberInfo in GetMappableMembers(dtype.InnerType).Where(m => !DataMember.IsPrimaryKey(m))) { Type returnType = MemberExpression.GetReturnType(memberInfo); //is this a collection of a mapped type? if so, ignore since this must be a 1-1, 1-many or many-many relationship and must be mapped somewhere else if (DataType.IsCollection(returnType) && IsMapped(returnType.GetCollectionItemType())) { continue; } //its a persistent type, with it's own table, map as a foreign key with one or more columns for the primary key if (IsMapped(returnType)) { //we asume this datatype is already mapped along with it's primery key DataType returnDataType = returnType; ForeignKey foreignKey = new ForeignKey(); foreignKey.Table = dtype.Table; foreignKey.RemoteTable = returnDataType.Table; foreignKey.Name = "FK_" + dtype.Name + "_" + memberInfo.Name + "_" + random.Next(); foreach (DataMember pk in returnDataType.PrimaryKey.ToList()) { Column column = new Column(); column.Name = memberInfo.Name + "_" + pk.Member.Expression.Replace('.', '_'); column.Table = dtype.Table; column.IsPrimaryKey = false; column.IsNullable = !RequiredValidator.IsRequired(memberInfo); column.DbType = DbTypeMapper.Parse(pk.Member.ReturnType); if (column.IsString) { column.Length = StringLengthValidator.GetMaxLength(pk.Member.FinalMemberInfo); } dtype.Table.Columns.Add(column); foreignKey.Columns.Add(new Tuple<Column, Column>(column, pk.Column)); //create datamember dtype.AddMember(memberInfo.Name + "." + pk.Member, column); } dtype.Table.ForeignKeys.Add(foreignKey); } //just map as a atomic value else { Column column = new Column(); column.Name = memberInfo.Name; column.Table = dtype.Table; column.IsNullable = !RequiredValidator.IsRequired(memberInfo); column.IsPrimaryKey = false; //create datamember DataMember dmember = dtype.AddMember(memberInfo.Name, column); //is this a regular atomic value? if (DbTypeMapper.DbTypeMap.ContainsValue(returnType) && returnType != typeof(object)) { column.DbType = DbTypeMapper.Parse(returnType); } else if (returnType.GetTypeInfo().IsEnum) { column.DbType = DbType.Int32; } //this is an non-atomic object, but its not mapped as a DataType, so we serialize it as json else { column.DbType = DbType.String; dmember.Converter = new Conversions.Json<object>(); } if (column.IsString) { column.Length = Data.Validation.StringLengthValidator.GetMaxLength(memberInfo); } dtype.Table.Columns.Add(column); } } yield return dtype; } }
public DataMember AddMember(string member, Column column) { var genericDataMemberType = typeof(DataMember<>).MakeGenericType(InnerType); ConstructorInfo constructor = genericDataMemberType.GetTypeInfo().DeclaredConstructors.Where(c => c.GetParameters().Length == 0).Single(); DataMember genericDataMember = (DataMember) constructor.Invoke(null); genericDataMember.Member = new MemberExpression(InnerType, member); if (column == null) { genericDataMember.CreateColumn(); } else { genericDataMember.Column = column; } DataMembers.Add(genericDataMember); return genericDataMember; }
/// <summary> /// Creates a new instance /// </summary> protected OrderBy(Column orderBy, SortDirection direction) { this.Column = orderBy; this.Direction = direction; }
/// <summary> /// Constructs the AggegateSelectField /// </summary> /// <param name="dataValue"> /// DataMember for build the field definition /// </param> public SelectColumn(Column column): this(column, null) { }
/// <summary> /// Creates the column and the agregate to the table. /// <para xml:lang="es"> /// Crea la columna y la agrega a la tabla. /// </para> /// </summary> public void CreateColumn() { var finalMember = Expression.FinalMemberInfo; var returnType = MemberExpression.GetReturnType(finalMember); Column = new Column() { Table = DataType.Table, Name = Expression.Expression.Replace('.', '_'), IsPrimaryKey = IsPrimaryKey(Expression), IsNullable = !RequiredValidator.IsRequired(finalMember) && !IsPrimaryKey(Expression), }; //is this a regular atomic value? if (Sql.DbTypeMapper.DbTypeMap.ContainsValue(returnType) && returnType != typeof(object)) { Column.DbType = Sql.DbTypeMapper.Parse(returnType); } else if (returnType.GetTypeInfo().IsEnum) { Column.DbType = Sql.DbType.Int32; } //this is an non-atomic object, but its not mapped as a DataType, so we serialize it as json else { Column.DbType = Sql.DbType.String; Converter = new Conversions.JsonConverter<object>(); } if (Column.IsString) { Column.Length = StringLengthValidator.GetMaxLength(finalMember); } if (MemberExpression.GetReturnType(finalMember) == typeof(Guid)) { Column.Length = 38; } Column.IsAutoNumber = Column.IsNumeric && Column.IsPrimaryKey && DataType.BaseDataType == null; DataType.Table.Columns.Add(Column); }
/// <summary> /// Returns the name of the specified field completly qualified /// </summary> /// <param name="column"> /// Column to format /// </param> /// <returns> /// Name of the specified field completly qualified /// </returns> protected virtual string ColumnFullName(Column column) { return EncloseName(column.Table.Name) + "." + EncloseName(column.Name); }
/// <summary> /// Constructs the AggegateSelectField /// </summary> /// <param name="dataValue"> /// DataMember for build the field definition /// </param> /// <param name="aggregateFunction"> /// Aggregate function to use for calculate the column /// </param> /// <param name="distinct"> /// Speficy if the DISTINCT modifier must be applied /// </param> /// <param name="alias"> /// Alias name of the resulting field /// </param> public SelectAggregateColumn(Column column, SelectAggregateFunction aggregateFunction, string alias, bool distinct): base(column, alias) { AggregateFunction = aggregateFunction; Distinct = distinct; }
/// <summary> /// Constructs the AggegateSelectField /// </summary> /// <param name="dataValue"> /// DataMember for build the field definition /// </param> /// <param name="aggregateFunction"> /// Aggregate function to use for calculate the column /// </param> /// <param name="alias"> /// Alias name of the resulting field /// </param> public SelectAggregateColumn(Column column, SelectAggregateFunction aggregateFunction, string alias) : this(column, aggregateFunction, alias, false) { }
/// <summary> /// Constructs the AggegateSelectField /// </summary> /// <param name="dataValue"> /// DataMember for build the field definition /// </param> /// <param name="aggregateFunction"> /// Aggregate function to use for calculate the column /// </param> public SelectAggregateColumn(Column column, SelectAggregateFunction aggregateFunction) : this(column, aggregateFunction, string.Empty) { }
/// <summary> /// Constructs the AggegateSelectField /// </summary> /// <param name="dataValue"> /// DataMember for build the field definition /// </param> public SelectAggregateColumn(Column column): this(column, SelectAggregateFunction.None) { }
public void CreateColumn() { var finalMember = Member.FinalMemberInfo; Column = new Column() { Table = DataType.Table, Name = Member.Expression.Replace('.', '_'), DbType = Sql.DbTypeMapper.Parse(MemberExpression.GetReturnType(finalMember)), IsNullable = !RequiredValidator.IsRequired(finalMember), IsPrimaryKey = IsPrimaryKey(finalMember), }; Column.IsAutoNumber = Column.IsNumeric && Column.IsPrimaryKey && DataType.BaseDataType == null; if (Column.IsString) { Column.Length = StringLengthValidator.GetMaxLength(finalMember); } DataType.Table.Columns.Add(Column); }
/// <summary> /// Add the member who brings as a parameter and creates a column for this member. /// <para xml:lang="es"> /// Agrega el miembro que trae como parametro y crea una columna para este miembro. /// </para> /// </summary> /// <returns>The member.</returns> /// <param name="member">Member. /// <para xml:lang="es">El Miembro.</para> /// </param> /// <param name="column">Column. /// <para xml:lang="es">La Columna.</para> /// </param> public DataMember AddMember(string member, Column column) { if (string.IsNullOrWhiteSpace(member)) { throw new ArgumentNullException(nameof(member)); } if (AllDataMembers.Where(dm => dm.Expression.Expression == member).Any()) { throw new ArgumentOutOfRangeException(string.Format("Member {0} is already mapped in DataType {1}", member, FullName)); } var genericDataMemberType = typeof(DataMember<>).MakeGenericType(InnerType); ConstructorInfo constructor = genericDataMemberType.GetTypeInfo().DeclaredConstructors.Where(c => c.GetParameters().Length == 0).Single(); DataMember genericDataMember = (DataMember) constructor.Invoke(null); genericDataMember.Expression = new MemberExpression(InnerType, member); //If there is no column for this member, create one. if (column == null) { genericDataMember.CreateColumn(); } //otherwise, it assigns the column that receives as a parameter else { genericDataMember.Column = column; } ((List<DataMember>) DataMembers).Add(genericDataMember); return genericDataMember; }
/// <summary> /// Returns the DML for create the column corresponding /// with the specified Column /// </summary> /// <param name="column"> /// Column for DML column creation /// </param> /// <returns> /// DML for create the column corresponding /// with the specified Column /// </returns> protected virtual Command CreateColumnClause(Column column) { //Append the column Name string columnDefinition = EncloseName(column.Name) + " "; //if this is a string value, format as a string if (column.IsString) { if (column.Length.HasValue && column.Length > 0) { columnDefinition += FormatStringType(column.Length.Value); } else { //unlimited lenght by default columnDefinition += FormatStringType(0); } } //otherwise, format normally else { columnDefinition += Format(column.DbType); } if (!column.IsNullable) { columnDefinition += " NOT " + Null; } else { columnDefinition += " " + Null; } //Append the AutoIncrement flag, only if column is not part of a foreign key if (column.IsAutoNumber) { columnDefinition += " " + AutoIncrementalSettingName; } //Returning the column definition return columnDefinition; }
/// <summary> /// Creates a new instance /// </summary> protected OrderBy(Column orderBy): this(orderBy, SortDirection.Ascending) { }
/// <summary> /// Returns the DML for create the column corresponding /// with the specified DataMember /// </summary> /// <param name="dataValue"> /// DataMember for DML column creation /// </param> /// <returns> /// DML for create the column corresponding /// with the specified DataMember /// </returns> protected override Command CreateColumnClause(Column column) { //if this is not an autoincrement column, use the base method if (!column.IsAutoNumber) { return base.CreateColumnClause(column); } //Append the column Name string columnDefinition = EncloseName(column.Name) + " "; //use Autoincrement as the TypeMap<T> columnDefinition += " " + AutoIncrementalSettingName; //Append the NULL flag if (!column.IsNullable) columnDefinition += " NOT " + Null; else columnDefinition += " " + Null; //Returning the column definition return columnDefinition; }