WITH [temp]({columns}, [Depth], [Path], [HasChildren]) AS
(
--初始查询(这里的 [ParentId] IS NULL 在数据中是最底层的根节点)
SELECT {columns},
0 AS [Depth],
'/' + CAST([Id] AS nvarchar(max)) + '/' AS [Path], --如果Id使用Guid类型,可能会导致层数太深时出问题(大概100层左右,超过4000字之后的字符串会被砍掉,sqlserver 2005以后用 nvarchar(max)可以突破限制),Guid的字数太多了
(CASE WHEN EXISTS(SELECT 1 FROM [{dataSourceName}] WHERE [{dataSourceName}].[ParentId] = [Root].[Id]) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END) AS [HasChildren]
FROM [{dataSourceName}] AS [Root]
WHERE [Root].[ParentId] IS NULL
UNION ALL
--递归条件
SELECT {child.columns},
[Parent].[Depth] + 1,
[Parent].[Path] + CAST([Child].[Id] AS nvarchar(max)) + '/' AS [Path],
(CASE WHEN EXISTS(SELECT 1 FROM [{dataSourceName}] WHERE [{dataSourceName}].[ParentId] = [Child].[Id]) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END) AS [HasChildren]
FROM [{dataSourceName}] AS [Child] --3:这里的临时表和原始数据表都必须使用别名不然递归的时候不知道查询的是哪个表的列
INNER JOIN [temp] AS [Parent]
ON ([Child].[ParentId] = [Parent].[Id]) --这个关联关系很重要,一定要理解一下谁是谁的父节点
)
--4:递归完成后 一定不要少了这句查询语句 否则会报错
SELECT *
FROM [temp];
GO
""";
private const string _dropSqlTemplate =
$"""
--删除可能存在的过时树形实体查询视图
IF EXISTS(SELECT * FROM [sysobjects] WHERE [id] = OBJECT_ID(N'{_viewNameTemplate}') AND objectproperty(id, N'IsView') = 1)
BEGIN
DROP VIEW [{_viewNameTemplate}]
END
GO
""";
public string CreateSqlTemplate => _createSqlTemplate;
public string DropSqlTemplate => _dropSqlTemplate;
public string? FormatTableOrColumnName(string? name)
else if (columnOperation is AlterColumnOperation alterColumn/* && alterColumn.OldColumn.Name is not null && alterColumn.Name != alterColumn.OldColumn.Name*/)
{
if (isUp)
{
if (thisVersionEntityTypes!.Any(et => et.GetTableName() == alterColumn.Table))
{
var entity = thisVersionEntityTypes!.Single(en => en.GetTableName() == alterColumn.Table);
'/' + CAST([Id] AS nvarchar(max)) + '/' AS [Path], --如果Id使用Guid类型,可能会导致层数太深时出问题(大概100层左右,超过4000字之后的字符串会被砍掉,sqlserver 2005以后用 nvarchar(max)可以突破限制),Guid的字数太多了
(CASE WHEN EXISTS(SELECT 1 FROM [QueryView_Entity2_1s] WHERE [QueryView_Entity2_1s].[ParentId] = [Root].[Id]) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END) AS [HasChildren]
[Parent].[Path] + CAST([Child].[Id] AS nvarchar(max)) + '/' AS [Path],
(CASE WHEN EXISTS(SELECT 1 FROM [QueryView_Entity2_1s] WHERE [QueryView_Entity2_1s].[ParentId] = [Child].[Id]) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END) AS [HasChildren]
FROM [QueryView_Entity2_1s] AS [Child] --3:这里的临时表和原始数据表都必须使用别名不然递归的时候不知道查询的是哪个表的列
INNER JOIN [temp] AS [Parent]
ON ([Child].[ParentId] = [Parent].[Id]) --这个关联关系很重要,一定要理解一下谁是谁的父节点
var modelInitializer = appDbContext.GetService<IModelRuntimeInitializer>();
var migrationsAssembly = appDbContext.GetService<IMigrationsAssembly>();
var modelDiffer = appDbContext.GetService<IMigrationsModelDiffer>();
var migrator = appDbContext.GetService<IMigrator>();
var firstModel = modelInitializer.Initialize(migrationsAssembly.CreateMigration(migrationsAssembly.Migrations.First().Value, appDbContext.Database.ProviderName!).TargetModel);
var snapshotModel = modelInitializer.Initialize(migrationsAssembly.ModelSnapshot!.Model);