- 增加 IDelete.ToSqlCascade 递归删除方法;

This commit is contained in:
2881099
2022-05-02 15:01:52 +08:00
parent fc3dc35617
commit 88d7985d92
4 changed files with 170 additions and 14 deletions

View File

@ -1,7 +1,12 @@
using FreeSql;
using FreeSql.DataAnnotations;
using FreeSql.Internal.CommonProvider;
using FreeSql.Internal.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Xunit;
namespace FreeSql.Tests.Sqlite
@ -104,3 +109,120 @@ namespace FreeSql.Tests.Sqlite
}
}
}
public static class DeleteExtensions
{
public static string ToSqlCascade<T>(this IDelete<T> that)
{
var delete = that as DeleteProvider;
if (delete == null) return null;
if (delete._whereTimes <= 0 || delete._where.Length == 0) return null;
if (LocalGetNavigates(delete._table).Any() == false) return that.ToSql();
var fsql = delete._orm;
var sb = new StringBuilder();
Dictionary<string, bool> eachdic = new Dictionary<string, bool>();
var rootSel = fsql.Select<object>().AsType(delete._table.Type).Where(delete._where.ToString());
var rootItems = rootSel.ToList();
LocalEach(delete._table.Type, rootItems, true);
return sb.ToString();
List<NativeTuple<TableRef, PropertyInfo>> LocalGetNavigates(TableInfo tb)
{
return tb.Properties.Where(a => tb.ColumnsByCs.ContainsKey(a.Key) == false)
.Select(a => new NativeTuple<TableRef, PropertyInfo>(tb.GetTableRef(a.Key, false), a.Value))
.Where(a => a.Item1 != null && a.Item1.RefType != TableRefType.ManyToOne)
.ToList();
}
void LocalEach(Type itemType, List<object> items, bool isOneToOne)
{
items = items?.Where(item =>
{
var itemKeystr = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetEntityKeyString(fsql, itemType, item, false);
var eachdicKey = $"{itemType.FullName},{itemKeystr}";
if (eachdic.ContainsKey(eachdicKey)) return false;
eachdic.Add(eachdicKey, true);
return true;
}).ToList();
if (items?.Any() != true) return;
var tb = fsql.CodeFirst.GetTableByEntity(itemType);
var navs = LocalGetNavigates(tb);
var otos = navs.Where(a => a.Item1.RefType == TableRefType.OneToOne).ToList();
if (otos.Any())
{
foreach (var oto in otos)
{
var childsSel = fsql.Select<object>().AsType(oto.Item1.RefEntityType) as Select1Provider<object>;
var refitems = items.Select(item =>
{
var refitem = oto.Item1.RefEntityType.CreateInstanceGetDefaultValue();
for (var a = 0; a < oto.Item1.Columns.Count; a++)
{
var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, oto.Item1.Columns[a].CsName);
FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childsSel._tables[0].Table, refitem, oto.Item1.RefColumns[a].CsName, colval);
}
return refitem;
}).ToList();
childsSel.Where(childsSel._commonUtils.WhereItems(oto.Item1.RefColumns.ToArray(), "a.", refitems));
var childs = childsSel.ToList();
LocalEach(oto.Item1.RefEntityType, childs, false);
}
}
var otms = navs.Where(a => a.Item1.RefType == TableRefType.OneToMany).ToList();
if (otms.Any())
{
foreach (var otm in otms)
{
var childsSel = fsql.Select<object>().AsType(otm.Item1.RefEntityType) as Select1Provider<object>;
var refitems = items.Select(item =>
{
var refitem = otm.Item1.RefEntityType.CreateInstanceGetDefaultValue();
for (var a = 0; a < otm.Item1.Columns.Count; a++)
{
var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, otm.Item1.Columns[a].CsName);
FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childsSel._tables[0].Table, refitem, otm.Item1.RefColumns[a].CsName, colval);
}
return refitem;
}).ToList();
childsSel.Where(childsSel._commonUtils.WhereItems(otm.Item1.RefColumns.ToArray(), "a.", refitems));
var childs = childsSel.ToList();
LocalEach(otm.Item1.RefEntityType, childs, true);
}
}
var mtms = navs.Where(a => a.Item1.RefType == TableRefType.ManyToMany).ToList();
if (mtms.Any())
{
foreach (var mtm in mtms)
{
var childsSel = fsql.Select<object>().AsType(mtm.Item1.RefMiddleEntityType) as Select1Provider<object>;
var miditems = items.Select(item =>
{
var refitem = mtm.Item1.RefMiddleEntityType.CreateInstanceGetDefaultValue();
for (var a = 0; a < mtm.Item1.Columns.Count; a++)
{
var colval = FreeSql.Extensions.EntityUtil.EntityUtilExtensions.GetPropertyValue(tb, item, mtm.Item1.Columns[a].CsName);
FreeSql.Extensions.EntityUtil.EntityUtilExtensions.SetPropertyValue(childsSel._tables[0].Table, refitem, mtm.Item1.MiddleColumns[a].CsName, colval);
}
return refitem;
}).ToList();
childsSel.Where(childsSel._commonUtils.WhereItems(mtm.Item1.MiddleColumns.Take(mtm.Item1.Columns.Count).ToArray(), "a.", miditems));
var childs = childsSel.ToList();
LocalEach(mtm.Item1.RefEntityType, childs, true);
}
}
var delSql = fsql.Delete<object>().AsType(itemType).WhereDynamic(items).ToSql();
if (string.IsNullOrWhiteSpace(delSql)) throw new Exception($"ToSqlCascade 失败");
if (sb.Length > 0) sb.Append("\r\n\r\n;\r\n\r\n");
sb.Append(delSql);
}
}
}

View File

@ -373,6 +373,8 @@ WHERE (((a.""Name"") in (SELECT s.""Title"" as1
var ddd = g.sqlite.Select<District>().LeftJoin(d => d.ParentCode == d.Parent.Code).ToTreeList();
Assert.Single(ddd);
Assert.Equal(2, ddd[0].Childs.Count);
var sql = g.sqlite.Delete<District>().Where(a => a.Code == "001").ToSqlCascade();
}
public class District
{
@ -1281,6 +1283,7 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
};
Assert.Equal(5, g.sqlite.Insert(model4s).ExecuteAffrows());
var by0 = g.sqlite.Select<TestInclude_OneToManyModel2>()
.Where(a => a.model2id <= model1.id)
.ToList();
@ -1305,6 +1308,8 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
.Where(a => a.id <= model1.id)
.ToList();
by1.IncludeByPropertyName(g.sqlite, "model2.childs", "model2111Idaaa=model2id");
by1.IncludeByPropertyNameAsync(g.sqlite, "model2.childs", "model2111Idaaa=model2id");
var t1 = g.sqlite.Select<TestInclude_OneToManyModel1>()
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id))
.Where(a => a.id <= model1.id)
@ -2233,6 +2238,8 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
})
});
var sql = g.sqlite.Delete<VM_District_Child>().Where(a => a.Code == "100000").ToSqlCascade();
var t1 = fsql.Select<VM_District_Parent>()
.InnerJoin(a => a.ParentCode == a.Parent.Code)
.Where(a => a.Code == "110101")