C#含深层嵌套与循环引用的数据库实体克隆方案咨询
支持循环引用的多层数据库实体克隆方案咨询
我有一个嵌套层级达8层的数据库实体,尝试使用带ReferenceHandler选项的System.Text.Json.Serializer,以及带ReferenceHandler.Ignore选项的JsonConvert.SerializeObject进行克隆,但均无响应(最长等待10分钟未返回)。现咨询是否有更优的支持循环引用的数据库实体克隆方案?
更新
我已基于C#反射技术实现了递归克隆功能,可处理循环引用并跳过无需克隆的实体(如我的场景中的参考表),能在微秒/秒级完成N层实体克隆,但该实现仍有优化精简空间,代码如下:
public object Clone(string[] skipEntites, Type circularType = null) { var newEntity = Activator.CreateInstance(this.GetType()); PropertyInfo[] entityProperties = newEntity.GetType().GetProperties(); foreach (PropertyInfo entityProperty in entityProperties) { var value = this.GetType().GetProperty(entityProperty.Name).GetValue(this); if (TryGetArgumentTypesFromHashSet(value, out Type[] argumentTypes)) { if (circularType != null && circularType.Name.Contains(argumentTypes[0].Name)) { continue; } Type hashSetType = typeof(HashSet<>).MakeGenericType(argumentTypes[0]); var hashSet = Activator.CreateInstance(hashSetType); MethodInfo addMethod = hashSetType.GetMethod("Add"); var entities = (IEnumerable)value; foreach (IEntity entity in entities) { addMethod.Invoke(hashSet, new object[] { entity.Clone(skipEntites, GetType()) }); } SetValue(entityProperty, hashSet, newEntity, skipEntites); continue; } if (value != null && circularType != null && circularType.Name.Contains(value.GetType().Name)) { continue; } if (circularType != null && circularType.Name.Contains(entityProperty.Name.Substring(0, entityProperty.Name.Length-2)) && entityProperty.Name.Contains("Id") && (entityProperty.PropertyType == typeof(int) || entityProperty.PropertyType == typeof(long) || entityProperty.PropertyType == typeof(int?) || entityProperty.PropertyType == typeof(long?)) ) { entityProperty.SetValue(newEntity, 0); continue; } SetValue(entityProperty, value, newEntity, skipEntites); } return newEntity; } private bool TryGetArgumentTypesFromHashSet(object value, out Type[] argumentTypes) { argumentTypes = null; if (value == null) { return false; } Type type = value.GetType(); argumentTypes = type.GetGenericArguments(); return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(HashSet<>) && argumentTypes.Length > 0; } private void SetValue(PropertyInfo entityProperty, object value, object newEntity, string[] skipEntites) { if (value != null && skipEntites.Any(x => value.GetType().Name.Contains(x))) { return; } if (value is IEntity referenceObject) { var newReference = referenceObject.Clone(skipEntites, GetType()); entityProperty.SetValue(newEntity, newReference); return; } if (entityProperty.Name == "Id" && (entityProperty.PropertyType == typeof(int) || entityProperty.PropertyType == typeof(long))) { entityProperty.SetValue(newEntity, 0); return; } entityProperty.SetValue(newEntity, value); }
内容的提问来源于stack exchange,提问作者ARr0w
相关产品推荐
相关产品推荐

