UpdateNavManyToMany.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using Newtonsoft.Json;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace SqlSugar
  9. {
  10. public partial class UpdateNavProvider<Root, T> where T : class, new() where Root : class, new()
  11. {
  12. private void UpdateManyToMany<TChild>(string name, EntityColumnInfo nav) where TChild : class, new()
  13. {
  14. var parentEntity = _ParentEntity;
  15. var parentList = _ParentList;
  16. var parentPkColumn = parentEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true);
  17. var parentNavigateProperty = parentEntity.Columns.FirstOrDefault(it => it.PropertyName == name);
  18. var thisEntity = this._Context.EntityMaintenance.GetEntityInfo<TChild>();
  19. var thisPkColumn = thisEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true);
  20. Check.ExceptionEasy(thisPkColumn == null, $"{thisPkColumn.EntityName} need primary key", $"{thisPkColumn.EntityName}需要主键");
  21. Check.ExceptionEasy(parentPkColumn == null, $"{parentPkColumn.EntityName} need primary key", $"{parentPkColumn.EntityName}需要主键");
  22. var mappingType = parentNavigateProperty.Navigat.MappingType;
  23. var mappingEntity = this._Context.EntityMaintenance.GetEntityInfo(mappingType);
  24. var mappingA = mappingEntity.Columns.FirstOrDefault(x => x.PropertyName == parentNavigateProperty.Navigat.MappingAId);
  25. var mappingB = mappingEntity.Columns.FirstOrDefault(x => x.PropertyName == parentNavigateProperty.Navigat.MappingBId);
  26. Check.ExceptionEasy(mappingA == null || mappingB == null, $"Navigate property {name} error ", $"导航属性{name}配置错误");
  27. var mappingPk = mappingEntity.Columns
  28. .Where(it => it.PropertyName != mappingA.PropertyName)
  29. .Where(it => it.PropertyName != mappingB.PropertyName)
  30. .Where(it => it.IsPrimarykey && !it.IsIdentity && it.OracleSequenceName.IsNullOrEmpty()).FirstOrDefault();
  31. var mappingOthers = mappingEntity.Columns
  32. .Where(it => it.PropertyName != mappingA.PropertyName)
  33. .Where(it => it.PropertyName != mappingB.PropertyName)
  34. .Where(it=>!it.IsIdentity)
  35. .Where(it => !it.IsPrimarykey)
  36. .Where(it => !it.IsOnlyIgnoreInsert)
  37. .Where(it => !it.IsIgnore);
  38. List<Dictionary<string, object>> mappgingTables = new List<Dictionary<string, object>>();
  39. var ids=new List<object>();
  40. foreach (var item in parentList)
  41. {
  42. var items = parentNavigateProperty.PropertyInfo.GetValue(item);
  43. if (items == null)
  44. {
  45. continue;
  46. }
  47. var children = ((List<TChild>)items);
  48. if (this._Options != null && this._Options.ManyToManyIsUpdateB)
  49. {
  50. InsertDatas(children, thisPkColumn);
  51. }
  52. else
  53. {
  54. _ParentList = children.Cast<object>().ToList();
  55. }
  56. var parentId = parentPkColumn.PropertyInfo.GetValue(item);
  57. if (!ids.Contains(parentId))
  58. {
  59. ids.Add(parentId);
  60. }
  61. foreach (var child in children)
  62. {
  63. var chidId = thisPkColumn.PropertyInfo.GetValue(child);
  64. Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
  65. keyValuePairs.Add(mappingA.DbColumnName, parentId);
  66. keyValuePairs.Add(mappingB.DbColumnName, chidId);
  67. if (mappingOthers != null)
  68. {
  69. foreach (var pair in mappingOthers)
  70. {
  71. if (pair.UnderType == UtilConstants.DateType)
  72. {
  73. keyValuePairs.Add(pair.DbColumnName, DateTime.Now);
  74. }
  75. else if (pair.UnderType == UtilConstants.StringType)
  76. {
  77. keyValuePairs.Add(pair.DbColumnName, UtilConstants.Space);
  78. }
  79. else
  80. {
  81. keyValuePairs.Add(pair.DbColumnName, UtilMethods.GetDefaultValue(pair.UnderType));
  82. }
  83. }
  84. }
  85. if (mappingPk != null)
  86. {
  87. SetMappingTableDefaultValue(mappingPk, keyValuePairs);
  88. }
  89. mappgingTables.Add(keyValuePairs);
  90. }
  91. }
  92. if (this._Options?.ManyToManyEnableLogicDelete == true)
  93. {
  94. var locgicColumn = thisEntity.Columns.FirstOrDefault(it => it.PropertyName.EqualCase("IsDeleted") || it.PropertyName.EqualCase("IsDelete"));
  95. Check.ExceptionEasy(
  96. locgicColumn == null,
  97. thisEntity.EntityName + "Logical deletion requires the entity to have the IsDeleted property",
  98. thisEntity.EntityName + "假删除需要实体有IsDeleted属性");
  99. List<IConditionalModel> conditionalModels = new List<IConditionalModel>();
  100. conditionalModels.Add(new ConditionalModel()
  101. {
  102. FieldName = mappingA.DbColumnName,
  103. FieldValue = string.Join(",", ids.Distinct()),
  104. ConditionalType = ConditionalType.In,
  105. CSharpTypeName = mappingA?.PropertyInfo?.PropertyType?.Name
  106. });
  107. var sqlObj = _Context.Queryable<object>().SqlBuilder.ConditionalModelToSql(conditionalModels);
  108. this._Context.Updateable<object>()
  109. .AS(mappingEntity.DbTableName)
  110. .Where(sqlObj.Key, sqlObj.Value)
  111. .SetColumns(locgicColumn.DbColumnName, true)
  112. .ExecuteCommand();
  113. }
  114. else if (_Context?.CurrentConnectionConfig?.MoreSettings?.IsAutoDeleteQueryFilter == true)
  115. {
  116. this._Context.Deleteable<object>().AS(mappingEntity.DbTableName).In(mappingA.DbColumnName, ids).EnableQueryFilter(mappingEntity.Type).ExecuteCommand();
  117. }
  118. else
  119. {
  120. this._Context.Deleteable<object>().AS(mappingEntity.DbTableName).In(mappingA.DbColumnName, ids).ExecuteCommand();
  121. }
  122. if (HasMappingTemplate(mappingEntity))
  123. {
  124. InertMappingWithTemplate(mappingEntity, mappingA, mappingB, mappgingTables);
  125. }
  126. else
  127. {
  128. this._Context.Insertable(mappgingTables).AS(mappingEntity.DbTableName).ExecuteCommand();
  129. }
  130. _ParentEntity = thisEntity;
  131. }
  132. private bool HasMappingTemplate(EntityInfo mappingEntity)
  133. {
  134. return this._Options?.ManyToManySaveMappingTemplate?.GetType() == mappingEntity.Type;
  135. }
  136. private void InertMappingWithTemplate(EntityInfo mappingEntity, EntityColumnInfo mappingA, EntityColumnInfo mappingB, List<Dictionary<string, object>> mappgingTables)
  137. {
  138. var template = this._Options?.ManyToManySaveMappingTemplate;
  139. List<object> mappingObjects = new List<object>();
  140. foreach (var item in mappgingTables)
  141. {
  142. // 序列化模板对象
  143. var serializedTemplate = JsonConvert.SerializeObject(template);
  144. // 反序列化模板对象,创建新的映射对象
  145. var mappingObject = JsonConvert.DeserializeObject(serializedTemplate, template.GetType());
  146. // 获取映射对象的所有字段
  147. var fields = mappingEntity.Columns;
  148. // 遍历字典中的键值对,并将值赋给映射对象的对应字段
  149. foreach (var kvp in item)
  150. {
  151. var fieldName = kvp.Key;
  152. var fieldValue = kvp.Value;
  153. // 查找与字段名匹配的字段
  154. var field = fields.FirstOrDefault(f => f.DbColumnName.EqualCase(fieldName));
  155. // 如果字段存在且值的类型与字段类型匹配,则赋值给字段
  156. if (field != null)
  157. {
  158. var isSetValue = field.IsPrimarykey
  159. || field.DbColumnName == mappingA.DbColumnName
  160. || field.DbColumnName == mappingB.DbColumnName;
  161. if (isSetValue)
  162. field.PropertyInfo.SetValue(mappingObject, fieldValue);
  163. }
  164. }
  165. // 将映射对象添加到列表中
  166. mappingObjects.Add(mappingObject);
  167. }
  168. this._Context.InsertableByObject(mappingObjects).ExecuteCommand();
  169. }
  170. private void SetMappingTableDefaultValue(EntityColumnInfo mappingPk, Dictionary<string, object> keyValuePairs)
  171. {
  172. if (mappingPk.UnderType == UtilConstants.LongType)
  173. {
  174. keyValuePairs.Add(mappingPk.DbColumnName, SnowFlakeSingle.Instance.NextId());
  175. }
  176. else if (mappingPk.UnderType == UtilConstants.GuidType)
  177. {
  178. keyValuePairs.Add(mappingPk.DbColumnName, Guid.NewGuid());
  179. }
  180. else if (mappingPk.UnderType == UtilConstants.StringType)
  181. {
  182. keyValuePairs.Add(mappingPk.DbColumnName, Guid.NewGuid() + "");
  183. }
  184. else
  185. {
  186. var name = mappingPk.EntityName + " " + mappingPk.DbColumnName;
  187. Check.ExceptionEasy($"The field {name} is not an autoassignment type and requires an assignment",
  188. $" 中间表主键字段{name}不是可自动赋值类型, 可赋值类型有 自增、long、Guid、string。你也可以删掉主键 用双主键");
  189. }
  190. }
  191. }
  192. }