diff --git a/.idea/.idea.HopFrame/.idea/workspace.xml b/.idea/.idea.HopFrame/.idea/workspace.xml
index b3204a1..5bfd32e 100644
--- a/.idea/.idea.HopFrame/.idea/workspace.xml
+++ b/.idea/.idea.HopFrame/.idea/workspace.xml
@@ -11,7 +11,15 @@
-
+
+
+
+
+
+
+
+
+
@@ -30,7 +38,7 @@
@@ -99,7 +107,7 @@
"RunOnceActivity.git.unshallow": "true",
"b5f11219-dfc4-47a1-b02c-90ab603034fb.executor": "Debug",
"dcdf1689-dc07-47e4-8824-2e60a4fbf301.executor": "Debug",
- "git-widget-placeholder": "!23 on feature/max-length",
+ "git-widget-placeholder": "!24 on fix/relations",
"list.type.of.created.stylesheet": "CSS",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
@@ -205,7 +213,7 @@
-
+
@@ -415,7 +423,15 @@
1738055497527
-
+
+
+ 1738055822074
+
+
+
+ 1738055822074
+
+
@@ -466,7 +482,6 @@
-
@@ -491,6 +506,7 @@
-
+
+
\ No newline at end of file
diff --git a/src/HopFrame.Core/Config/PropertyConfig.cs b/src/HopFrame.Core/Config/PropertyConfig.cs
index 7c8070c..bc1df99 100644
--- a/src/HopFrame.Core/Config/PropertyConfig.cs
+++ b/src/HopFrame.Core/Config/PropertyConfig.cs
@@ -200,4 +200,16 @@ public class PropertyConfigurator(PropertyConfig config) {
InnerConfig.DisplayLength = maxLength;
return this;
}
+
+ ///
+ /// Forces a property to be treated as a relation
+ ///
+ /// Determines if it is possible to assign multiple objects to the property
+ /// Determines if the property is nullable
+ public PropertyConfigurator ForceRelation(bool isEnumerable = false, bool isRequired = true) {
+ InnerConfig.IsRelation = true;
+ InnerConfig.IsEnumerable = isEnumerable;
+ InnerConfig.IsRequired = isRequired;
+ return this;
+ }
}
diff --git a/src/HopFrame.Core/Services/Implementations/ContextExplorer.cs b/src/HopFrame.Core/Services/Implementations/ContextExplorer.cs
index cbb2f16..33cd8f6 100644
--- a/src/HopFrame.Core/Services/Implementations/ContextExplorer.cs
+++ b/src/HopFrame.Core/Services/Implementations/ContextExplorer.cs
@@ -1,6 +1,7 @@
using System.Text.Json;
using HopFrame.Core.Config;
using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace HopFrame.Core.Services.Implementations;
@@ -56,15 +57,35 @@ internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider pr
private void SeedTableData(TableConfig table) {
if (table.Seeded) return;
- var dbContext = (provider.GetService(table.ContextConfig.ContextType) as DbContext)!;
+ var dbContext = (provider.GetRequiredService(table.ContextConfig.ContextType) as DbContext)!;
var entity = dbContext.Model.FindEntityType(table.TableType)!;
foreach (var propertyConfig in table.Properties) {
if (propertyConfig.IsListingProperty) continue;
+ if (propertyConfig.IsRelation) continue;
+
var prop = entity.FindProperty(propertyConfig.Info.Name);
if (prop is not null) continue;
+
var nav = entity.FindNavigation(propertyConfig.Info.Name);
- if (nav is null) continue;
+ if (nav is null) {
+ if (!propertyConfig.Info.PropertyType.IsGenericType) continue;
+ var relationType = propertyConfig.Info.PropertyType.GenericTypeArguments[0];
+
+ var isRelation = entity.Model.GetEntityTypes()
+ .Select(e => e.GetForeignKeys())
+ .Any(keys => keys
+ .Select(k => k.PrincipalEntityType.ClrType)
+ .Any(t => t == relationType || t == table.TableType));
+ if (!isRelation) continue;
+
+ propertyConfig.IsRelation = true;
+ propertyConfig.IsRequired = false;
+ propertyConfig.IsEnumerable = true;
+
+ continue;
+ }
+
propertyConfig.IsRelation = true;
propertyConfig.IsRequired = nav.ForeignKey.IsRequired;
propertyConfig.IsEnumerable = nav.IsCollection;
@@ -74,7 +95,7 @@ internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider pr
var propConfig = table.Properties
.Where(prop => !prop.IsListingProperty)
.SingleOrDefault(prop => prop.Info == property.PropertyInfo);
- if (propConfig is null) continue;
+ if (propConfig is null || propConfig.IsRequired) continue;
propConfig.IsRequired = !property.IsNullable;
}
diff --git a/testing/HopFrame.Testing/DatabaseContext.cs b/testing/HopFrame.Testing/DatabaseContext.cs
index 7abb091..b596cbb 100644
--- a/testing/HopFrame.Testing/DatabaseContext.cs
+++ b/testing/HopFrame.Testing/DatabaseContext.cs
@@ -12,8 +12,7 @@ public class DatabaseContext(DbContextOptions options) : DbCont
base.OnModelCreating(modelBuilder);
modelBuilder.Entity()
- .HasOne(p => p.Author)
- .WithMany(u => u.Posts)
- .OnDelete(DeleteBehavior.Cascade);
+ .HasOne(p => p.Author)
+ .WithMany(u => u.Posts);
}
}
\ No newline at end of file
diff --git a/testing/HopFrame.Testing/Program.cs b/testing/HopFrame.Testing/Program.cs
index d743d3b..e18f72f 100644
--- a/testing/HopFrame.Testing/Program.cs
+++ b/testing/HopFrame.Testing/Program.cs
@@ -95,6 +95,6 @@ app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents()
.AddInteractiveServerRenderMode()
- .MapHopFramePages();
+ .AddHopFramePages();
app.Run();
\ No newline at end of file