private static void ProcessManagedProperties(Type type, DbTable table, EntityMeta em) { foreach (var property in em.EntityProperties) { var meta = property.ColumnMeta; if (meta == null) { continue; } var propertyName = property.Name; //生成 ManagedPropertyBridge var epm = em.Property(propertyName); if (epm == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", type.FullName, propertyName)); } var mp = epm.ManagedProperty as IProperty; //列名 var columnName = meta.ColumnName; if (string.IsNullOrWhiteSpace(columnName)) { columnName = propertyName; } var column = table.CreateColumn(columnName, epm); column.IsIdentity = meta.IsIdentity; column.IsPrimaryKey = meta.IsPrimaryKey; table.Add(column); } }
private static void ProcessManagedProperties(Type type, PersistanceTableInfo table, EntityMeta em) { foreach (var property in em.EntityProperties) { var meta = property.ColumnMeta; if (meta == null) { continue; } var propertyName = property.Name; //生成 ManagedPropertyBridge var epm = em.Property(propertyName); if (epm == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", type.FullName, propertyName)); } var column = new PersistanceColumnInfo(epm, meta, table); if (meta.IsPrimaryKey) { table.PKColumn = column; } table.Columns.Add(column); } }
/// <summary> /// 禁用实体的幽灵(假删除)功能。 /// </summary> /// <param name="meta"></param> public static void DisablePhantoms(this EntityMeta meta) { meta.IsPhantomEnabled = false; meta.Property(EntityPhantomExtension.IsPhantomProperty).DontMapColumn(); meta.DeletingChildrenInMemory = false; }
private void TrySetProperty(Entity e, string pName, JToken value) { //有些小写的客户端数据被传输到了服务端,需要被过滤掉。 if (char.IsLower(pName[0])) { return; } var pm = _entityMeta.Property(pName) as PropertyMeta ?? _entityMeta.ChildrenProperty(pName); if (pm != null) { var mp = pm.ManagedProperty; if (mp is IListProperty) { //todo: 此处的性能可能需要优化,聚合保存子列表时,重复的查询 Repository var entityType = EntityMatrix.FindByList(pm.PropertyType).EntityType; var repo = RF.Find(entityType); //列表属性的设置不能使用 SetProperty,否则,list.Parent 将会无值。 //但是也不能直接使用 LoadProperty,否则会导致调用 list.MarkOld,从而不会保存这个列表。 //所以只能先装载一个空列表,然后再把 json 中的数据转换为实体加入到这个列表中。 var list = repo.NewList(); e.LoadProperty(mp, list); ListReader.JsonToEntity(value as JObject, repo, list); } else { var rawValue = (value as JValue).Value; rawValue = EntityJsonConverter.ToServerValue(pm.PropertyType, rawValue); e.SetProperty(mp, rawValue, ManagedPropertyChangedSource.FromUIOperating); } } else { var rawValue = (value as JValue).Value; //如果没有找到一般的属性,则尝试查找外键属性 for (int i = 0, c = _refIdProperties.Count; i < c; i++) { var rip = _refIdProperties[i]; if (rip.Name == pName) { e.SetRefId(rip, rawValue); break; } } //只读属性。 //if(notFound) //{ // throw new InvalidOperationException("没有在实体中找到这个属性:" + pName); //} } }
/// <summary> /// 启用实体的幽灵(假删除)功能。 /// </summary> /// <param name="meta"></param> public static void EnablePhantoms(this EntityMeta meta) { meta.IsPhantomEnabled = true; meta.Property(EntityPhantomExtension.IsPhantomProperty).MapColumn(); //使用假删除插件后,需要把整个聚合中的所有数据都标识为‘幽灵’状态,所有的聚合子都需要在内存中也进行假删除。 //如果在插件打开此功能后,这个功能不应该被关闭,否则会影响插件的一些功能。 meta.DeletingChildrenInMemory = true; }
private static void ProcessManagedProperties(Type type, PersistanceTableInfo table, EntityMeta em) { foreach (var property in em.EntityProperties) { var meta = property.ColumnMeta; if (meta == null) { continue; } var propertyName = property.Name; //生成 ManagedPropertyBridge var epm = em.Property(propertyName); if (epm == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", type.FullName, propertyName)); } var mp = epm.ManagedProperty as IProperty; //列名 var columnName = meta.ColumnName; if (string.IsNullOrWhiteSpace(columnName)) { columnName = propertyName; } var column = new PersistanceColumnInfo { Table = table, Name = columnName, DataType = epm.PropertyType, IsIdentity = meta.IsIdentity, IsPrimaryKey = meta.IsPrimaryKey, Property = mp }; if (meta.IsPrimaryKey) { table.PKColumn = column; } table.Columns.Add(column); } }
private static void ProcessManagedProperties(Type type, PersistanceTableInfo table, EntityMeta em) { foreach (var property in em.EntityProperties) { var meta = property.ColumnMeta; if (meta == null) continue; var propertyName = property.Name; //生成 ManagedPropertyBridge var epm = em.Property(propertyName); if (epm == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", type.FullName, propertyName)); } var mp = epm.ManagedProperty as IProperty; //列名 var columnName = meta.ColumnName; if (string.IsNullOrWhiteSpace(columnName)) columnName = propertyName; var column = new PersistanceColumnInfo { Table = table, Name = columnName, DataType = epm.PropertyType, IsIdentity = meta.IsIdentity, IsPrimaryKey = meta.IsPrimaryKey, Property = mp }; if (meta.IsPrimaryKey) { table.PKColumn = column; } table.Columns.Add(column); } }
private static void ProcessManagedProperties( RdbTableInfo table, EntityMeta em, IDbIdentifierQuoter identifierProvider, DbTypeConverter dbTypeConverter ) { foreach (var property in em.EntityProperties) { var columnMeta = property.ColumnMeta; if (columnMeta == null) { continue; } var propertyName = property.Name; var epm = em.Property(propertyName); if (epm == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", em.EntityType.FullName, propertyName)); } var columnName = identifierProvider.Prepare(columnMeta.ColumnName); var dbType = columnMeta.DbType ?? dbTypeConverter.FromClrType(epm.PropertyType);; var column = new RdbColumnInfo(columnName, epm, columnMeta, table, dbType); if (columnMeta.IsPrimaryKey) { table.PKColumn = column; } table.Columns.Add(column); } }
/// <summary> /// 根据实体类型创建表的描述信息,并添加到数据库中 /// </summary> /// <param name="em">The memory.</param> /// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.InvalidOperationException">refMeta.ReferenceInfo == null</exception> private void BuildTable(EntityMeta em) { var tableMeta = em.TableMeta; //视图类不需要支持数据库迁移。 if (tableMeta.IsMappingView) { return; } var table = new Table(tableMeta.TableName, this.Database); //读取实体的注释 if (_readComment) { table.Comment = _commentFinder.TryFindComment(em.EntityType); } var metaProperties = em.EntityProperties; //var managedProperties = ManagedPropertyRepository.Instance // .GetTypePropertiesContainer(em.EntityType) // .GetNonReadOnlyCompiledProperties(); foreach (var property in metaProperties) { var columnMeta = property.ColumnMeta; if (columnMeta == null) { continue; } var mp = property.ManagedProperty; if (mp == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", em.Name, mp.Name)); } //列名 var propertyName = property.Name; var columnName = columnMeta.ColumnName; if (string.IsNullOrWhiteSpace(columnName)) { columnName = propertyName; } //类型 var propertyType = property.PropertyType; bool isNullableRef = false; #region 引用关系 if (columnMeta.HasFKConstraint) { var refProperty = mp as IRefProperty; if (refProperty != null) { isNullableRef = refProperty.Nullable; var refMeta = em.Property(refProperty.RefEntityProperty); if (refMeta.ReferenceInfo == null) { throw new InvalidOperationException("refMeta.ReferenceInfo == null"); } //引用实体的类型。 var refTypeMeta = refMeta.ReferenceInfo.RefTypeMeta; if (refTypeMeta != null) { var refTableMeta = refTypeMeta.TableMeta; if (refTableMeta != null) { //如果主键表已经被忽略,那么到这个表上的外键也不能建立了。 //这是因为被忽略的表的结构是未知的,不一定是以这个字段为主键。 if (!this.Database.IsIgnored(refTableMeta.TableName)) { var id = refTypeMeta.Property(Entity.IdProperty); //有时一些表的 Id 只是自增长,但并不是主键,不能创建外键。 if (id.ColumnMeta.IsPrimaryKey) { this._foreigns.Add(new ForeignConstraintInfo() { FkTableName = tableMeta.TableName, PkTableName = refTableMeta.TableName, FkColumn = columnName, PkColumn = id.ColumnMeta.ColumnName, NeedDeleteCascade = refProperty.ReferenceType == ReferenceType.Parent }); } } } } } else if (mp == Entity.TreePIdProperty) { var id = em.Property(Entity.IdProperty); //有时一些表的 Id 只是自增长,但并不是主键,不能创建外键。 if (id.ColumnMeta.IsPrimaryKey) { this._foreigns.Add(new ForeignConstraintInfo() { FkTableName = tableMeta.TableName, PkTableName = tableMeta.TableName, FkColumn = columnName, PkColumn = id.ColumnMeta.ColumnName, NeedDeleteCascade = false }); } } } #endregion var dataType = TypeHelper.IgnoreNullable(propertyType); //对于支持多数据类型的 Id、TreePId 属性进行特殊处理。 if (mp == Entity.IdProperty || mp == Entity.TreePIdProperty) { dataType = em.IdType; } var dbType = columnMeta.DataType.GetValueOrDefault(DbTypeHelper.ConvertFromCLRType(dataType)); var column = new Column(columnName, dbType, columnMeta.DataTypeLength, table); if (columnMeta.IsRequired.HasValue) { column.IsRequired = columnMeta.IsRequired.Value; } else { column.IsRequired = !isNullableRef && !propertyType.IsClass && !TypeHelper.IsNullable(propertyType); } //IsPrimaryKey 的设置放在 IsRequired 之后,可以防止在设置可空的同时把列调整为非主键。 column.IsPrimaryKey = columnMeta.IsPrimaryKey; column.IsIdentity = columnMeta.IsIdentity; table.Columns.Add(column); //读取属性的注释。 if (_readComment) { var commentProperty = mp; var refProperty = commentProperty as IRefProperty; if (refProperty != null) { commentProperty = refProperty.RefEntityProperty; } column.Comment = _commentFinder.TryFindComment(commentProperty); } } table.SortColumns(); this.AddTable(table); }
private static void MapDefaultColumns(EntityMeta meta) { if (meta.TableMeta != null) { foreach (var ep in meta.EntityProperties) { var mp = ep.ManagedProperty; //Id 属性,默认的元数据中,即是主键,也是自增长列。应用层可以考虑再做配置。 if (mp == EntityConvention.Property_Id) { ep.ColumnMeta = new ColumnMeta { ColumnName = mp.Name, IsPrimaryKey = true, }; if (meta.IdType == typeof(int) || meta.IdType == typeof(long)) { ep.ColumnMeta.IsIdentity = true; } } //其它属性 else if (mp != EntityConvention.Property_TreeIndex && mp != EntityConvention.Property_TreePId) { var clrProperty = ep.CLRProperty; if (clrProperty != null) { var columnAttri = clrProperty.GetSingleAttribute<ColumnAttribute>(); if (columnAttri != null) { var name = columnAttri.ColumnName; if (string.IsNullOrWhiteSpace(name)) name = clrProperty.Name; ep.ColumnMeta = new ColumnMeta { ColumnName = name }; } } } } //树的两个属性 if (meta.IsTreeEntity) { var p = meta.Property(EntityConvention.Property_TreeIndex); if (p != null) { p.MapColumn(); } p = meta.Property(EntityConvention.Property_TreePId); if (p != null) { p.MapColumn(); } } } }
/// <summary> /// 根据实体类型创建表的描述信息,并添加到数据库中 /// </summary> /// <param name="em">The memory.</param> /// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.InvalidOperationException">refMeta.ReferenceInfo == null</exception> private void BuildTable(EntityMeta em) { var tableMeta = em.TableMeta; //视图类不需要支持数据库迁移。 if (tableMeta.IsMappingView) { return; } var table = new Table(tableMeta.TableName, this.Database); var metaProperties = em.EntityProperties; //var managedProperties = ManagedPropertyRepository.Instance // .GetTypePropertiesContainer(em.EntityType) // .GetNonReadOnlyCompiledProperties(); foreach (var property in metaProperties) { var columnMeta = property.ColumnMeta; if (columnMeta == null) continue; var mp = property.ManagedProperty; if (mp == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", em.Name, mp.Name)); } //列名 var propertyName = property.Name; var columnName = columnMeta.ColumnName; if (string.IsNullOrWhiteSpace(columnName)) columnName = propertyName; //类型 var propertyType = property.PropertyType; bool isNullableRef = false; #region 引用关系 if (columnMeta.HasFKConstraint) { var refProperty = mp as IRefProperty; if (refProperty != null) { isNullableRef = refProperty.Nullable; var refMeta = em.Property(refProperty.RefEntityProperty); if (refMeta.ReferenceInfo == null) throw new InvalidOperationException("refMeta.ReferenceInfo == null"); //引用实体的类型。 var refTypeMeta = refMeta.ReferenceInfo.RefTypeMeta; if (refTypeMeta != null) { var refTableMeta = refTypeMeta.TableMeta; if (refTableMeta != null) { //如果主键表已经被忽略,那么到这个表上的外键也不能建立了。 //这是因为被忽略的表的结构是未知的,不一定是以这个字段为主键。 if (!this.Database.IsIgnored(refTableMeta.TableName)) { var id = refTypeMeta.Property(Entity.IdProperty); //有时一些表的 Id 只是自增长,但并不是主键,不能创建外键。 if (id.ColumnMeta.IsPrimaryKey) { this._foreigns.Add(new ForeignConstraintInfo() { FkTableName = tableMeta.TableName, PkTableName = refTableMeta.TableName, FkColumn = columnName, PkColumn = id.ColumnMeta.ColumnName, NeedDeleteCascade = refProperty.ReferenceType == ReferenceType.Parent }); } } } } } else if (mp == Entity.TreePIdProperty) { var id = em.Property(Entity.IdProperty); //有时一些表的 Id 只是自增长,但并不是主键,不能创建外键。 if (id.ColumnMeta.IsPrimaryKey) { this._foreigns.Add(new ForeignConstraintInfo() { FkTableName = tableMeta.TableName, PkTableName = tableMeta.TableName, FkColumn = columnName, PkColumn = id.ColumnMeta.ColumnName, NeedDeleteCascade = false }); } } } #endregion var dataType = TypeHelper.IgnoreNullable(propertyType); //对于支持多数据类型的 Id、TreePId 属性进行特殊处理。 if (mp == Entity.IdProperty || mp == Entity.TreePIdProperty) { dataType = em.IdType; } var dbType = columnMeta.DataType.GetValueOrDefault(DbTypeHelper.ConvertFromCLRType(dataType)); var column = new Column(dbType, columnMeta.DataTypeLength, columnName, table); if (columnMeta.IsRequired.HasValue) { column.IsRequired = columnMeta.IsRequired.Value; } else { column.IsRequired = !isNullableRef && !propertyType.IsClass && !TypeHelper.IsNullable(propertyType); } //IsPrimaryKey 的设置放在 IsRequired 之后,可以防止在设置可空的同时把列调整为非主键。 column.IsPrimaryKey = columnMeta.IsPrimaryKey; column.IsIdentity = columnMeta.IsIdentity; table.Columns.Add(column); } table.SortColumns(); this.AddTable(table); }