/// <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 void DataTypeTest() { var dtype = new DataType<OKHOSTING.ORM.Tests.Model.Person>(); dtype.Validators.Add(new MemberValidator(dtype[m => m.Firstname].Member, new StringLengthValidator(100))); }
/// <summary> /// Create DataMember. /// <para xml:lang="es">Crea el DataMember</para> /// </summary> /// <param name="type"></param> /// <param name="member"></param> public DataMember(DataType type, string member): this(type, member, null) { }
/// <summary> /// Creates a new data type based on the table that receives as argument, only members who have a column with the same name /// <para xml:lang="es"> /// Crea un nuevo tipo de datos basado en la tabla que reciba como argumento, solo miembros que tienen una columna con el mismo nombre /// </para> /// </summary> public static DataType DefaultMap(Type type, Table table) { if (type == null) { throw new ArgumentNullException("type"); } if (table == null) { throw new ArgumentNullException("table"); } if (IsMapped(type)) { throw new ArgumentOutOfRangeException("type", "This Types is already mapped"); } DataType dtype = new DataType(type, table); foreach (MemberInfo memberInfo in GetMappableMembers(type)) { if (dtype.Table.Columns.Where(c => c.Name == memberInfo.Name).Count() > 0) { dtype.AddMember(memberInfo.Name, dtype.Table[memberInfo.Name]); TypeInfo returnType = MemberExpression.GetReturnType(memberInfo).GetTypeInfo(); if (returnType.Equals(typeof(DataType).GetTypeInfo()) || returnType.IsSubclassOf(typeof(DataType))) { dtype[memberInfo.Name].Converter = new Conversions.DataTypeConverter(); } else if (returnType.Equals(typeof(Type).GetTypeInfo())) { dtype[memberInfo.Name].Converter = new Conversions.TypeConverter(); } else if (returnType.Equals(typeof(object).GetTypeInfo()) && IsMapped(returnType.AsType())) { dtype[memberInfo.Name].Converter = new Conversions.PersistentObjectConverter(); } } } return dtype; }
/// <summary> /// Creates a list of new DataTypes, creating as well a list of new Tables with all members of type as columns /// <para xml:lang="es"> /// Crea una lista de tipos de datos nuevos, creando asà una lista de nuevas tablas con todos los miembros de tipo como columnas /// </para> /// </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()) { DataMember dmember = dtype.AddMember(memberInfo.Name + "." + pk.Expression); dmember.Column.Name = memberInfo.Name + "_" + pk.Expression.Expression.Replace('.', '_'); dmember.Column.IsPrimaryKey = false; dmember.Column.IsNullable = !RequiredValidator.IsRequired(memberInfo); foreignKey.Columns.Add(new Tuple<Column, Column>(dmember.Column, pk.Column)); } dtype.Table.ForeignKeys.Add(foreignKey); } //just map as a atomic value else { //create datamember dtype.AddMember(memberInfo.Name); } } foreach (var memberInfo in GetMappableMembers(dtype.InnerType)) { foreach (var att in memberInfo.GetCustomAttributes()) { var validator = att as ValidatorBase; if (validator == null) { continue; } MemberValidator memberValidator = new MemberValidator(new MemberExpression(memberInfo.DeclaringType, memberInfo.Name), validator); dtype.Validators.Add(memberValidator); } } yield return dtype; } }
/// <summary> /// Determines whether an instance of the current /// TypeMap(T) is assignable from another TypeMap(T) /// <para xml:lang="es"> /// Determina si hay una instancia del TypeMap(T) /// actual que sea asignable de otro TipeMap(T). /// </para> /// </summary> public bool IsAssignableFrom(DataType typeMap) { //Validating if the argument is null if (typeMap == null) throw new ArgumentNullException("typeMap"); //Validating... return this.InnerType.GetTypeInfo().IsAssignableFrom(typeMap.InnerType.GetTypeInfo()); }
/// <summary> /// Compare this TypeMap(T)'s instance with another to see if they are the same /// <para xml:lang="es"> /// Compara este caso de TypeMap(T) con otro para ver si son los mismos. /// </para> /// </summary> public bool Equals(DataType typeMap) { //Validating if the argument is null if (typeMap == null) throw new ArgumentNullException("typeMap"); //Comparing the InnerType types return this.InnerType.Equals(typeMap.InnerType); }
/// <summary> /// Converts a DataType to it's string representantion /// </summary> /// <param name="value"> /// DataType to be converted to string /// </param> /// <returns> /// A string representation of DataType /// </returns> public static string ToString(DataType value) { //null values if (value == null) return null; return value.FullName; }
/// <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; } }
/// <summary> /// Creates a new DataType based on an existing Table, matching only members that have a column with the same name /// </summary> public static DataType DefaultMap(Type type, Table table) { if (type == null) { throw new ArgumentNullException("type"); } if (table == null) { throw new ArgumentNullException("table"); } if (IsMapped(type)) { throw new ArgumentOutOfRangeException("type", "This Types is already mapped"); } DataType dtype = new DataType(type, table); foreach (var memberInfo in GetMappableMembers(type)) { if (dtype.Table.Columns.Where(c => c.Name == memberInfo.Name).Count() > 0) { dtype.AddMember(memberInfo.Name, dtype.Table[memberInfo.Name]); } } return dtype; }