From 621966d9ea2c433d2ba9e907908316842528d3a8 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Thu, 10 Sep 2020 11:15:06 -0700 Subject: [PATCH] Add RelationalModel debug property to Model Improve RelationalModel DebugView Fixes #22309 --- .../Extensions/RelationalModelExtensions.cs | 22 +++++++- .../Metadata/SqlQueryExtensions.cs | 8 ++- .../Metadata/StoreFunctionExtensions.cs | 25 +++++++++ .../Metadata/TableExtensions.cs | 54 +++++++++++++++++++ .../Metadata/ViewExtensions.cs | 8 ++- src/EFCore/Metadata/Internal/Model.cs | 9 ++++ 6 files changed, 123 insertions(+), 3 deletions(-) diff --git a/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs b/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs index e87eb9ebe95..aa07995f82f 100644 --- a/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalModelExtensions.cs @@ -41,7 +41,12 @@ public static string ToDebugString( var builder = new StringBuilder(); var indentString = new string(' ', indent); - builder.Append(indentString).Append("DatabaseModel: "); + builder.Append(indentString).Append("RelationalModel: "); + + if (model.Collation != null) + { + builder.AppendLine().Append(indentString).Append("Collation: " + model.Collation); + } foreach (var table in model.Tables) { @@ -53,6 +58,21 @@ public static string ToDebugString( builder.AppendLine().Append(view.ToDebugString(options, indent + 2)); } + foreach (var function in model.Functions) + { + builder.AppendLine().Append(function.ToDebugString(options, indent + 2)); + } + + foreach (var query in model.Queries) + { + builder.AppendLine().Append(query.ToDebugString(options, indent + 2)); + } + + foreach (var sequence in model.Sequences) + { + builder.AppendLine().Append(sequence.ToDebugString(options, indent + 2)); + } + if ((options & MetadataDebugStringOptions.IncludeAnnotations) != 0) { builder.Append(model.AnnotationsToDebugString(indent)); diff --git a/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs b/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs index 1b4407f2a83..e58e2e28654 100644 --- a/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs +++ b/src/EFCore.Relational/Metadata/SqlQueryExtensions.cs @@ -55,6 +55,12 @@ public static string ToDebugString( if ((options & MetadataDebugStringOptions.SingleLine) == 0) { + if (sqlQuery.Sql != null) + { + builder.AppendLine().Append(indentString).Append(" Sql: "); + builder.AppendLine().Append(indentString).Append(new string(' ', 4)).Append(sqlQuery.Sql); + } + var mappings = sqlQuery.EntityTypeMappings.ToList(); if (mappings.Count != 0) { @@ -68,7 +74,7 @@ public static string ToDebugString( var columns = sqlQuery.Columns.ToList(); if (columns.Count != 0) { - builder.AppendLine().Append(indentString).Append(" Properties: "); + builder.AppendLine().Append(indentString).Append(" Columns: "); foreach (var column in columns) { builder.AppendLine().Append(column.ToDebugString(options, indent + 4)); diff --git a/src/EFCore.Relational/Metadata/StoreFunctionExtensions.cs b/src/EFCore.Relational/Metadata/StoreFunctionExtensions.cs index e6105acb759..c47a6b836cc 100644 --- a/src/EFCore.Relational/Metadata/StoreFunctionExtensions.cs +++ b/src/EFCore.Relational/Metadata/StoreFunctionExtensions.cs @@ -58,6 +58,11 @@ public static string ToDebugString( builder.Append(function.Name); + if (function.IsBuiltIn) + { + builder.Append(" IsBuiltIn"); + } + if ((options & MetadataDebugStringOptions.SingleLine) == 0) { var parameters = function.Parameters.ToList(); @@ -70,6 +75,26 @@ public static string ToDebugString( } } + var mappings = function.EntityTypeMappings.ToList(); + if (mappings.Count != 0) + { + builder.AppendLine().Append(indentString).Append(" EntityTypeMappings: "); + foreach (var mapping in mappings) + { + builder.AppendLine().Append(mapping.ToDebugString(options, indent + 4)); + } + } + + var columns = function.Columns.ToList(); + if (columns.Count != 0) + { + builder.AppendLine().Append(indentString).Append(" Columns: "); + foreach (var column in columns) + { + builder.AppendLine().Append(column.ToDebugString(options, indent + 4)); + } + } + if ((options & MetadataDebugStringOptions.IncludeAnnotations) != 0) { builder.Append(function.AnnotationsToDebugString(indent: indent + 2)); diff --git a/src/EFCore.Relational/Metadata/TableExtensions.cs b/src/EFCore.Relational/Metadata/TableExtensions.cs index 57c32cb4dcd..67ead53c010 100644 --- a/src/EFCore.Relational/Metadata/TableExtensions.cs +++ b/src/EFCore.Relational/Metadata/TableExtensions.cs @@ -52,6 +52,30 @@ public static string ToDebugString( builder.Append(" ExcludedFromMigrations"); } + if (table.PrimaryKey == null) + { + builder.Append(" Keyless"); + } + else + { + if ((options & MetadataDebugStringOptions.SingleLine) == 0) + { + builder.AppendLine(); + } + + builder.Append(table.PrimaryKey.ToDebugString(options, indent + 2)); + } + + if ((options & MetadataDebugStringOptions.SingleLine) == 0 && table.Comment != null) + { + builder + .AppendLine() + .Append(indentString) + .AppendLine(" Comment:") + .Append(indentString) + .Append(table.Comment); + } + if ((options & MetadataDebugStringOptions.SingleLine) == 0) { var mappings = table.EntityTypeMappings.ToList(); @@ -74,6 +98,36 @@ public static string ToDebugString( } } + var foreignKeyConstraints = table.ForeignKeyConstraints.ToList(); + if (foreignKeyConstraints.Count != 0) + { + builder.AppendLine().Append(indentString).Append(" ForeignKeyConstraints: "); + foreach (var foreignKeyConstraint in foreignKeyConstraints) + { + builder.AppendLine().Append(foreignKeyConstraint.ToDebugString(options, indent + 4)); + } + } + + var indexes = table.Indexes.ToList(); + if (indexes.Count != 0) + { + builder.AppendLine().Append(indentString).Append(" Indexes: "); + foreach (var index in indexes) + { + builder.AppendLine().Append(index.ToDebugString(options, indent + 4)); + } + } + + var uniqueConstraints = table.UniqueConstraints.Where(uc => !uc.GetIsPrimaryKey()).ToList(); + if (uniqueConstraints.Count != 0) + { + builder.AppendLine().Append(indentString).Append(" UniqueConstraints: "); + foreach (var uniqueConstraint in uniqueConstraints) + { + builder.AppendLine().Append(uniqueConstraint.ToDebugString(options, indent + 4)); + } + } + var checkConstraints = table.CheckConstraints.ToList(); if (checkConstraints.Count != 0) { diff --git a/src/EFCore.Relational/Metadata/ViewExtensions.cs b/src/EFCore.Relational/Metadata/ViewExtensions.cs index d1af9949656..5f3d61eb995 100644 --- a/src/EFCore.Relational/Metadata/ViewExtensions.cs +++ b/src/EFCore.Relational/Metadata/ViewExtensions.cs @@ -49,6 +49,12 @@ public static string ToDebugString( if ((options & MetadataDebugStringOptions.SingleLine) == 0) { + if (view.ViewDefinitionSql != null) + { + builder.AppendLine().Append(indentString).Append(" DefinitionSql: "); + builder.AppendLine().Append(indentString).Append(new string(' ', 4)).Append(view.ViewDefinitionSql); + } + var mappings = view.EntityTypeMappings.ToList(); if (mappings.Count != 0) { @@ -62,7 +68,7 @@ public static string ToDebugString( var columns = view.Columns.ToList(); if (columns.Count != 0) { - builder.AppendLine().Append(indentString).Append(" Properties: "); + builder.AppendLine().Append(indentString).Append(" Columns: "); foreach (var column in columns) { builder.AppendLine().Append(column.ToDebugString(options, indent + 4)); diff --git a/src/EFCore/Metadata/Internal/Model.cs b/src/EFCore/Metadata/Internal/Model.cs index 0385c0d9a24..483446322f3 100644 --- a/src/EFCore/Metadata/Internal/Model.cs +++ b/src/EFCore/Metadata/Internal/Model.cs @@ -1025,6 +1025,15 @@ public virtual bool SkipDetectChanges return skipDetectChanges; } + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public virtual object RelationalModel + => this["Relational:RelationalModel"]; + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in