diff --git a/Directory.Build.props b/Directory.Build.props
index 9aacfc7..8fd10af 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -4,4 +4,7 @@
$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))
+
+
+
diff --git a/src/Abstractions/Dgmjr.EntityFrameworkCore.Abstractions.csproj b/src/Abstractions/Dgmjr.EntityFrameworkCore.Abstractions.csproj
index ce077a0..a28a1ef 100644
--- a/src/Abstractions/Dgmjr.EntityFrameworkCore.Abstractions.csproj
+++ b/src/Abstractions/Dgmjr.EntityFrameworkCore.Abstractions.csproj
@@ -37,7 +37,7 @@
-
+
diff --git a/src/Abstractions/IDbContext.cs b/src/Abstractions/IDbContext.cs
index 00e997a..7623cab 100644
--- a/src/Abstractions/IDbContext.cs
+++ b/src/Abstractions/IDbContext.cs
@@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Abstractions;
using Microsoft.EntityFrameworkCore;
+// [GenerateInterface(typeof(DbContext))]
+// public partial interface IDbContext { }
+
/// An abstraction (interface) for a .
public partial interface IDbContext //: IAsyncDisposable
{
diff --git a/src/Extensions/DesignTimeDbContextFactory.cs b/src/Extensions/DesignTimeDbContextFactory.cs
new file mode 100644
index 0000000..fc54452
--- /dev/null
+++ b/src/Extensions/DesignTimeDbContextFactory.cs
@@ -0,0 +1,63 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.Extensions.Configuration;
+using Microsoft.EntityFrameworkCore.SqlServer;
+
+namespace Microsoft.EntityFrameworkCore.Design;
+
+public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory
+ where TContext : DbContext
+{
+ public virtual IConfigurationBuilder Configure(IConfigurationBuilder configBuilder)
+ {
+ return configBuilder
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
+ .AddJsonFile(
+ $"appsettings.{env.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json",
+ optional: true
+ )
+ .AddEnvironmentVariables()
+ .AddUserSecrets()
+ .AddUserSecrets(GetType().Assembly, optional: true, reloadOnChange: true);
+ }
+
+ public virtual SqlServerDbContextOptionsBuilder Configure(
+ SqlServerDbContextOptionsBuilder optionsBuilder
+ )
+ {
+ #if NET8_0_OR_GREATER
+ return optionsBuilder = optionsBuilder.UseAzureSqlDefaults();
+ #endif
+ return optionsBuilder;
+ }
+
+ protected virtual string GetConnectionString(IConfiguration configuration)
+ {
+ return configuration.GetConnectionString(typeof(TContext).Name.Replace("Context", ""))
+ ?? configuration.GetConnectionString(
+ typeof(TContext).Name.Replace(nameof(DbContext), "")
+ );
+ }
+
+ protected virtual DbContextOptionsBuilder Configure(DbContextOptionsBuilder builder)
+ {
+ return builder;
+ }
+
+ public virtual TContext CreateDbContext(string[] args)
+ {
+ var configuration = Configure(new ConfigurationBuilder()).AddCommandLine(args).Build();
+
+ return (Activator.CreateInstance(
+ typeof(TContext),
+ Configure(new DbContextOptionsBuilder()
+ .UseSqlServer(
+ GetConnectionString(configuration)
+ ?? configuration.GetConnectionString("DefaultConnection")
+ ?? "Server=(localdb)\\mssqllocaldb;Database=EFProviders.InMemory;Trusted_Connection=True;MultipleActiveResultSets=true",
+ x => Configure(x)
+ ))
+ .Options
+ ) as TContext)!;
+ }
+}
diff --git a/src/Extensions/Dgmjr.EntityFrameworkCore.Extensions.csproj b/src/Extensions/Dgmjr.EntityFrameworkCore.Extensions.csproj
index 97cce03..652a387 100644
--- a/src/Extensions/Dgmjr.EntityFrameworkCore.Extensions.csproj
+++ b/src/Extensions/Dgmjr.EntityFrameworkCore.Extensions.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/src/Migrations/CreateViewOperation.cs b/src/Migrations/CreateViewOperation.cs
new file mode 100644
index 0000000..c5f8bbb
--- /dev/null
+++ b/src/Migrations/CreateViewOperation.cs
@@ -0,0 +1,11 @@
+// namespace Dgmjr.EntityFrameworkCore.Migrations;
+
+// public class CreateViewOperation(string schema, string name, params Column[] columns) : SqlOperation
+// {
+// public string Schema { get; set; } = schema;
+// public string Name { get; set; } = name;
+// public Column[] Columns { get; set; } = columns;
+// public Expression
+// }
+
+// public record struct Column(string DataType, string SourceTable, string ColumnName);
diff --git a/src/Models/Dgmjr.EntityFrameworkCore.Models.csproj b/src/Models/Dgmjr.EntityFrameworkCore.Models.csproj
index 46d0c29..925e88b 100644
--- a/src/Models/Dgmjr.EntityFrameworkCore.Models.csproj
+++ b/src/Models/Dgmjr.EntityFrameworkCore.Models.csproj
@@ -21,6 +21,7 @@
+
diff --git a/src/Models/Slug.cs b/src/Models/Slug.cs
new file mode 100644
index 0000000..91b7e14
--- /dev/null
+++ b/src/Models/Slug.cs
@@ -0,0 +1,72 @@
+namespace Dgmjr.EntityFrameworkCore;
+using static Vogen.Conversions;
+using Vogen;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+public readonly partial struct Slug(string Value) : IComparable, IEquatable, IComparable
+{
+ public Slug()
+ : this(NewSlug()) { }
+
+ public string Value { get; init; } = Value;
+
+ public int CompareTo(Slug other)
+ => Compare(Value, other.Value, OrdinalIgnoreCase);
+
+ public int CompareTo(object obj)
+ => obj is Slug other ? CompareTo(other) : 1;
+
+ public static string NewSlug()
+ => guid.NewGuid().ToString("N").Substring(0, 6).ToLowerInvariant();
+
+ public override string ToString()
+ => Value;
+
+ public bool Equals(Slug other)
+ => CompareTo(other) == 0;
+
+ public override bool Equals(object? obj)
+ => obj is Slug other && Equals(other);
+
+ public static bool operator==(Slug left, Slug right)
+ => left.Equals(right);
+
+ public static bool operator!=(Slug left, Slug right)
+ => !left.Equals(right);
+}
+
+public class SlugEfCoreConverter : ValueConverter
+{
+ public SlugEfCoreConverter() : this(null) { }
+ public SlugEfCoreConverter(ConverterMappingHints? mappingHints = null)
+ : base(v => v.Value, v => v.ToSlug(), mappingHints) { }
+}
+
+public class SlugJsonConverter : JsonConverter
+{
+ public override Slug Read(ref Utf8JsonReader reader, type typeToConvert, Jso options)
+ => new(reader.GetString());
+
+ public override void Write(Utf8JsonWriter writer, Slug value, Jso options)
+ => writer.WriteStringValue(value.Value);
+}
+
+public class SlugTypeConfiguration : IEntityTypeConfiguration
+ where TEntity : class, IIdentifiable
+{
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.HasKey(e => e.Id);
+ builder.Property(e => e.Id).ValueGeneratedNever();
+ builder.Property(e => e.Id).HasConversion(v => v.Value, v => v.ToSlug());
+ }
+}
+
+public static class SlugExtensions
+{
+ public static Slug ToSlug(this string value)
+ => new(value);
+
+ public static Slug NewSlug()
+ => new();
+}