Added automatic relation mapping

This commit is contained in:
2025-01-16 15:30:52 +01:00
parent 9d9f0ef7e4
commit c3c69466d4
9 changed files with 71 additions and 41 deletions

View File

@@ -79,10 +79,4 @@ public class PropertyConfig<TProp>(PropertyConfig config) {
InnerConfig.DisplayValue = display;
return this;
}
public PropertyConfig<TProp> IsRelation(bool isRelation) {
InnerConfig.IsRelation = isRelation;
return this;
}
}

View File

@@ -8,8 +8,10 @@ namespace HopFrame.Core.Config;
public class TableConfig {
public Type TableType { get; }
public string PropertyName { get; }
public string DisplayName { get; set; }
public DbContextConfig ContextConfig { get; }
public bool Ignored { get; set; }
internal bool Seeded { get; set; }
public List<PropertyConfig> Properties { get; } = new();
@@ -17,6 +19,7 @@ public class TableConfig {
TableType = tableType;
PropertyName = propertyName;
ContextConfig = config;
DisplayName = PropertyName;
foreach (var info in tableType.GetProperties()) {
var propConfig = new PropertyConfig(info, this);
@@ -55,6 +58,11 @@ public class TableConfig<TModel>(TableConfig config) {
configurator.Invoke(prop);
return this;
}
public TableConfig<TModel> SetDisplayName(string name) {
InnerConfig.DisplayName = name;
return this;
}
internal static PropertyInfo GetPropertyInfo<TSource, TProperty>(Expression<Func<TSource, TProperty>> propertyLambda) {
if (propertyLambda.Body is not MemberExpression member) {

View File

@@ -4,7 +4,7 @@ namespace HopFrame.Core.Services;
public interface IContextExplorer {
public IEnumerable<string> GetTableNames();
public TableConfig? GetTable(string tableName);
public TableConfig? GetTable(string tableDisplayName);
public TableConfig? GetTable(Type tableEntity);
public ITableManager? GetTableManager(string tableName);
public ITableManager? GetTableManager(string tablePropertyName);
}

View File

@@ -1,23 +1,26 @@
using HopFrame.Core.Config;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace HopFrame.Core.Services.Implementations;
internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider provider) : IContextExplorer {
internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider provider, ILogger<ContextExplorer> logger) : IContextExplorer {
public IEnumerable<string> GetTableNames() {
foreach (var context in config.Contexts) {
foreach (var table in context.Tables) {
if (table.Ignored) continue;
yield return table.PropertyName;
yield return table.DisplayName;
}
}
}
public TableConfig? GetTable(string tableName) {
public TableConfig? GetTable(string tableDisplayName) {
foreach (var context in config.Contexts) {
var table = context.Tables.FirstOrDefault(table => table.PropertyName.Equals(tableName, StringComparison.CurrentCultureIgnoreCase));
if (table is not null)
return table;
var table = context.Tables.FirstOrDefault(table => table.DisplayName.Equals(tableDisplayName, StringComparison.CurrentCultureIgnoreCase));
if (table is null) continue;
SeedTableData(table);
return table;
}
return null;
@@ -26,16 +29,18 @@ internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider pr
public TableConfig? GetTable(Type tableEntity) {
foreach (var context in config.Contexts) {
var table = context.Tables.FirstOrDefault(table => table.TableType == tableEntity);
if (table is not null)
return table;
if (table is null) continue;
SeedTableData(table);
return table;
}
return null;
}
public ITableManager? GetTableManager(string tableName) {
public ITableManager? GetTableManager(string tablePropertyName) {
foreach (var context in config.Contexts) {
var table = context.Tables.FirstOrDefault(table => table.PropertyName == tableName);
var table = context.Tables.FirstOrDefault(table => table.PropertyName == tablePropertyName);
if (table is null) continue;
var dbContext = provider.GetService(context.ContextType) as DbContext;
@@ -48,4 +53,20 @@ internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider pr
return null;
}
private void SeedTableData(TableConfig table) {
if (table.Seeded) return;
var dbContext = (provider.GetService(table.ContextConfig.ContextType) as DbContext)!;
var entity = dbContext.Model.FindEntityType(table.TableType)!;
foreach (var key in entity.GetForeignKeys()) {
var propConfig = table.Properties
.SingleOrDefault(prop => prop.Info == key.DependentToPrincipal?.PropertyInfo);
if (propConfig is null) continue;
propConfig.IsRelation = true;
}
logger.LogInformation("Extracted information for table '" + table.PropertyName + "'");
table.Seeded = true;
}
}

View File

@@ -5,7 +5,7 @@
@using HopFrame.Web.Components.Pages
<FluentDialogBody Style="overflow-x: auto">
<HopFrameTablePage DisplayActions="false" DisplaySelection="true" TableName="@Content.SourceTable.PropertyName" PerPage="15" DialogData="Content" />
<HopFrameTablePage DisplayActions="false" DisplaySelection="true" TableDisplayName="@Content.SourceTable.DisplayName" PerPage="15" DialogData="Content" />
</FluentDialogBody>
@code {

View File

@@ -1,4 +1,4 @@
@page "/admin/{TableName}"
@page "/admin/{TableDisplayName}"
@layout HopFrameLayout
@rendermode InteractiveServer
@implements IDisposable
@@ -13,7 +13,7 @@
<div style="display: flex; flex-direction: column; height: 100%">
<FluentToolbar Class="hopframe-toolbar">
<h3>@_config?.PropertyName</h3>
<h3>@_config?.DisplayName</h3>
<FluentButton
IconStart="@(new Icons.Regular.Size16.ArrowClockwise())"
OnClick="Reload"
@@ -120,7 +120,7 @@
@code {
[Parameter]
public required string TableName { get; set; }
public required string TableDisplayName { get; set; }
[Parameter]
public bool DisplaySelection { get; set; }
@@ -145,9 +145,9 @@
private int _selectedIndex = -1;
protected override void OnInitialized() {
_config ??= Explorer.GetTable(TableName);
_config ??= Explorer.GetTable(TableDisplayName);
if (_config is null) {
if (_config is null || (_config.Ignored && DialogData is null)) {
Navigator.NavigateTo("/admin", true);
}
}