/// <summary> /// /// </summary> /// <param name="relProperty"></param> /// <param name="thisType"></param> /// <param name="otherType"></param> /// <returns></returns> private static RelationshipMetadata CachedRelationshipMetadata(RelationProperty relProperty, Type thisType, Type otherType) { if (relationCache.TryGetValue(thisType.Assembly, out SafetyDictionary <string, RelationshipMetadata> relations)) { var key = string.Format("{0}:{1}:{2}", EntityMetadataUnity.GetEntityMetadata(thisType).TableName, EntityMetadataUnity.GetEntityMetadata(otherType).TableName, relProperty.Name); return(relations.GetOrAdd(key, () => MakeRelationshipMetadata(relProperty, thisType, otherType))); } return(null); }
/// <summary> /// 根据规则获取实体关系。 /// </summary> /// <param name="relProperty"></param> /// <returns></returns> private static RelationshipMetadata GetMetadataByAssignment(RelationProperty relProperty) { switch (relProperty.RelationalPropertyType) { case RelationPropertyType.Entity: return(CachedRelationshipMetadata(relProperty, relProperty.RelationalType, relProperty.EntityType)); case RelationPropertyType.EntitySet: return(CachedRelationshipMetadata(relProperty, relProperty.EntityType, relProperty.RelationalType)); case RelationPropertyType.RefProperty: break; } return(null); }
/// <summary> /// 根据规则获取实体关系。 /// </summary> /// <param name="relProperty"></param> /// <returns></returns> private static RelationshipMetadata GetMetadataByRule(RelationProperty relProperty) { switch (relProperty.RelationPropertyType) { case RelationPropertyType.Entity: return(MakeOne2ManyMetadataCached(relProperty.RelationType, relProperty.EntityType)); case RelationPropertyType.EntitySet: return(MakeOne2ManyMetadataCached(relProperty.EntityType, relProperty.RelationType)); case RelationPropertyType.RefProperty: var p = relProperty as ReferenceProperty; break; } return(null); }
/// <summary> /// Copy ctor /// </summary> /// <param name="vCard">The vCard to clone.</param> private VCard(VCard vCard) { Version = vCard.Version; Func <ICloneable?, object?> cloner = Cloned; foreach (KeyValuePair <VCdProp, object> kvp in vCard._propDic) { Set(kvp.Key, kvp.Value switch { XmlProperty xmlProp => xmlProp.Clone(), IEnumerable <XmlProperty?> xmlPropEnumerable => xmlPropEnumerable.Select(cloner).Cast <XmlProperty?>().ToArray(), ProfileProperty profProp => profProp.Clone(), TextProperty txtProp => txtProp.Clone(), IEnumerable <TextProperty?> txtPropEnumerable => txtPropEnumerable.Select(cloner).Cast <TextProperty?>().ToArray(), DateTimeProperty dtTimeProp => dtTimeProp.Clone(), IEnumerable <DateTimeProperty?> dtTimePropEnumerable => dtTimePropEnumerable.Select(cloner).Cast <DateTimeProperty?>().ToArray(), AddressProperty adrProp => adrProp.Clone(), IEnumerable <AddressProperty?> adrPropEnumerable => adrPropEnumerable.Select(cloner).Cast <AddressProperty?>().ToArray(), NameProperty nameProp => nameProp.Clone(), IEnumerable <NameProperty?> namePropEnumerable => namePropEnumerable.Select(cloner).Cast <NameProperty?>().ToArray(), RelationProperty relProp => relProp.Clone(), IEnumerable <RelationProperty?> relPropEnumerable => relPropEnumerable.Select(cloner).Cast <RelationProperty?>().ToArray(), OrganizationProperty orgProp => orgProp.Clone(), IEnumerable <OrganizationProperty?> orgPropEnumerable => orgPropEnumerable.Select(cloner).Cast <OrganizationProperty?>().ToArray(), StringCollectionProperty strCollProp => strCollProp.Clone(), IEnumerable <StringCollectionProperty?> strCollPropEnumerable => strCollPropEnumerable.Select(cloner).Cast <StringCollectionProperty?>().ToArray(), GenderProperty sexProp => sexProp.Clone(), IEnumerable <GenderProperty?> sexPropEnumerable => sexPropEnumerable.Select(cloner).Cast <GenderProperty?>().ToArray(), GeoProperty geoProp => geoProp.Clone(), IEnumerable <GeoProperty?> geoPropEnumerable => geoPropEnumerable.Select(cloner).Cast <GeoProperty?>().ToArray(), DataProperty dataProp => dataProp.Clone(), IEnumerable <DataProperty?> dataPropEnumerable => dataPropEnumerable.Select(cloner).Cast <DataProperty?>().ToArray(), NonStandardProperty nStdProp => nStdProp.Clone(), IEnumerable <NonStandardProperty?> nStdPropEnumerable => nStdPropEnumerable.Select(cloner).Cast <NonStandardProperty?>().ToArray(), PropertyIDMappingProperty pidMapProp => pidMapProp.Clone(), IEnumerable <PropertyIDMappingProperty?> pidMapPropEnumerable => pidMapPropEnumerable.Select(cloner).Cast <PropertyIDMappingProperty?>().ToArray(), TimeZoneProperty tzProp => tzProp.Clone(), IEnumerable <TimeZoneProperty?> tzPropEnumerable => tzPropEnumerable.Select(cloner).Cast <TimeZoneProperty?>().ToArray(), ICloneable cloneable => cloneable.Clone(), // AccessProperty, KindProperty, TimeStampProperty, UuidProperty _ => kvp.Value });
/// <summary> /// 使用主键和外键对应构造一对多的关系。 /// </summary> /// <param name="relProperty"></param> /// <param name="thisType"></param> /// <param name="otherType"></param> /// <returns></returns> private static RelationshipMetadata MakeRelationshipMetadata(RelationProperty relProperty, Type thisType, Type otherType) { //是否使用了 ForeignKeyAttribute 来指定对应的外键 var assignAttr = relProperty.Info.ReflectionInfo.GetCustomAttributes <RelationshipAssignAttribute>().FirstOrDefault(); if (assignAttr != null) { var fkPro = PropertyUnity.GetProperty(otherType, assignAttr.ForeignKey); var pkPro = PropertyUnity.GetProperty(thisType, assignAttr.PrimaryKey); if (fkPro != null && pkPro != null) { var key = new RelationshipKey { ThisKey = pkPro.Name, ThisProperty = pkPro, OtherKey = fkPro.Name, OtherProperty = fkPro }; return(new RelationshipMetadata(thisType, otherType, RelationshipStyle.One2Many, RelationshipSource.AutomaticallyAssign, new[] { key })); } } //使用名称相同的主键进行匹配 var pks = PropertyUnity.GetPrimaryProperties(thisType).ToList(); if (pks.Count > 0) { var fks = pks.Select(s => PropertyUnity.GetProperty(otherType, s.Name)).ToList(); var keys = new RelationshipKey[pks.Count]; for (var i = 0; i < pks.Count; i++) { if (fks[i] == null) { throw new Exception(); } keys[i] = new RelationshipKey { ThisKey = pks[i].Name, ThisProperty = pks[i], OtherKey = fks[i].Name, OtherProperty = fks[i] }; } return(new RelationshipMetadata(thisType, otherType, RelationshipStyle.One2Many, RelationshipSource.AutomaticallyAssign, keys)); } return(null); }
/// <summary> /// 将实体的所有主键值赋给关联的实体属性。 /// </summary> /// <param name="entity"></param> /// <param name="relationPro"></param> /// <param name="enumerable"></param> internal static void AttachPrimaryKeyValues(IEntity entity, RelationProperty relationPro, IEnumerable enumerable) { var relationKey = RelationshipUnity.GetRelationship(relationPro); if (relationKey == null) { return; } var action = GetAttachPrimaryKeyAction(enumerable.GetType().GetEnumerableElementType()); foreach (IEntity item in enumerable) { if (item.EntityState != EntityState.Attached) { continue; } foreach (var key in relationKey.Keys) { action(item, key.OtherProperty, entity.InternalGetValue(key.ThisProperty)); } } }
/// <summary> /// 构造函数, /// 支持的格式有: /// this.LivingCityId=foreign.CityId /// LivingCityId=CityId /// this.CityId /// CityId /// </summary> public RelationAttribute(params string[] relationPropertys) { RelationPropertys = new RelationProperty[relationPropertys.Length]; for (int i = 0; i < relationPropertys.Length; i++) { string relationProperty = relationPropertys[i]; string[] relationPropertySplit = relationProperty.Split(SPLIT_CHARS_EQUALS, StringSplitOptions.RemoveEmptyEntries); if (relationPropertySplit.Length > 1) { string[] leftSplit = relationPropertySplit[0].Split(SPLIT_CHARS_POINT, StringSplitOptions.RemoveEmptyEntries); string[] rightSplit = relationPropertySplit[1].Split(SPLIT_CHARS_POINT, StringSplitOptions.RemoveEmptyEntries); string left = leftSplit.Length > 1 ? leftSplit[1] : leftSplit[0]; string right = rightSplit.Length > 1 ? rightSplit[1] : rightSplit[0]; RelationPropertys[i] = new RelationProperty(left, right); } else { string[] leftSplit = relationPropertySplit[0].Split(SPLIT_CHARS_POINT, StringSplitOptions.RemoveEmptyEntries); string left = leftSplit.Length > 1 ? leftSplit[1] : leftSplit[0]; RelationPropertys[i] = new RelationProperty(left, left); } } }
private static RelationshipMetadata CheckSingleKey(IEnumerable <RelationshipMetadata> list, RelationProperty relationPro) { foreach (var item in list) { if (item.Style == RelationshipStyle.One2Many && item.ThisType == relationPro.RelationType && item.OtherType == relationPro.EntityType) { if (!string.IsNullOrEmpty(relationPro.RelationKey)) { if (item.Keys.Any(s => s.OtherKey == relationPro.RelationKey)) { return(item); } } else { return(item); } } else if (item.Style == RelationshipStyle.Many2One && item.ThisType == relationPro.EntityType && item.OtherType == relationPro.RelationType) { if (!string.IsNullOrEmpty(relationPro.RelationKey)) { if (item.Keys.Any(s => s.ThisKey == relationPro.RelationKey)) { return(item); } } else { return(item); } } } return(null); }
private static RelationshipMetadata CheckSetKey(IEnumerable <RelationshipMetadata> list, RelationProperty relationPro) { return(list.FirstOrDefault(item => (item.ThisType == relationPro.EntityType && item.OtherType == relationPro.RelationType && item.Style == RelationshipStyle.One2Many) || (item.ThisType == relationPro.RelationType && item.OtherType == relationPro.EntityType && item.Style == RelationshipStyle.Many2One))); }
internal static SqlCommand BuildEntitySetQuery(EntityQueryContext context, IEntity entity, RelationProperty relationProperty) { var relationKey = RelationshipUnity.GetRelationship(relationProperty); if (relationKey == null || relationKey.Style != RelationshipStyle.One2Many) { return(null); } var query = new EntityQueryBuilder(context, relationProperty.RelationType) .Select().All().From(); var valid = true; foreach (var key in relationKey.Keys) { var val = entity.InternalGetValue(key.ThisProperty); if (PropertyValue.IsNullOrEmpty(val) || !val.IsValid) { valid = false; continue; } query = query.And(key.OtherProperty, entity.InternalGetValue(key.ThisProperty)); } if (!valid) { return(string.Empty); } return(query.ToSqlCommand()); }
internal static SqlCommand BuildEntityQuery(EntityQueryContext context, IEntity entity, RelationProperty relationProperty) { var relationKey = RelationshipUnity.GetRelationship(relationProperty); if (relationKey == null) { return(null); } Type relationType; Func <RelationshipKey, IProperty> func1, func2; if (entity.EntityType == relationKey.ThisType) { relationType = relationKey.OtherType; func1 = key => key.OtherProperty; func2 = key => key.ThisProperty; } else { relationType = relationKey.ThisType; func1 = key => key.ThisProperty; func2 = key => key.OtherProperty; } var query = new EntityQueryBuilder(context, relationType) .Select().All().From(); foreach (var key in relationKey.Keys) { var val = entity.InternalGetValue(func2(key)); if (PropertyValue.IsNullOrEmpty(val) || !val.IsValid) { return(string.Empty); } query = query.And(func1(key), val); } return(query.ToSqlCommand()); }