Skip to content

Commit

Permalink
Add new utility features and refactorings
Browse files Browse the repository at this point in the history
Introduced Humanizer dependency for enhanced text manipulation capabilities in shared build configuration. Commented out Dgmjr.InterfaceGenerator references in Abstraction project, indicating a potential shift in code generation strategy or removal of dependency. Prepared IDbContext interface for future feature through commented interface generation directive.

Implemented a DesignTimeDbContextFactory with environment-specific configuration and Azure SQL support for streamlined database context creation during design time. Additionally, a Slug value object, complete with comparison functionality and JSON/EF Core converters, was introduced to provide standardized identity handling across models.

Removed version override for Dgmjr.System.Extensions, signaling a move to rely on the package's default available version for better compatibility or maintainability. Lastly, laid groundwork for CreateViewOperation in Migrations, which suggests upcoming migration operation support, albeit the feature remains commented out for future development.

Note: The rationale behind commenting out code rather than removal hints at temporary suspensions for possible reevaluation.

References: #12345 (if applicable)
  • Loading branch information
dgmjr committed Feb 21, 2024
1 parent c7ae9df commit 011e24d
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 2 deletions.
3 changes: 3 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
<InheritedDirectoryBuildProps>$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))</InheritedDirectoryBuildProps>
</PropertyGroup>
<Import Project="$(InheritedDirectoryBuildProps)" />
<ItemGroup>
<PackageReference Include="Humanizer.Core" VersionOverride="[2.14.1,)" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="System.Collections.Generic.Usings" />
<PackageReference Include="System.Text.Json" />
<PackageReference Include="Dgmjr.InterfaceGenerator" IncludeAssets="Analyzers;Build" ExcludeAssets="Native;BuildTransitive;BuildMultitargeting;ContentFiles;Compile;Runtime" PrivateAssets="All" />
<!-- <PackageReference Include="Dgmjr.InterfaceGenerator" IncludeAssets="Analyzers;Build" ExcludeAssets="Native;BuildTransitive;BuildMultitargeting;ContentFiles;Compile;Runtime" PrivateAssets="All" /> -->
<!-- <PackageReference Include="Dgmjr.InterfaceGenerator.Decomposer" IncludeAssets="Analyzers;Build" ExcludeAssets="Native;BuildTransitive;BuildMultitargeting;ContentFiles;Compile;Runtime" PrivateAssets="All" /> -->
</ItemGroup>
<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions src/Abstractions/IDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ namespace Microsoft.EntityFrameworkCore.Abstractions;

using Microsoft.EntityFrameworkCore;

// [GenerateInterface(typeof(DbContext))]
// public partial interface IDbContext { }

/// <summary>An abstraction (interface) for a <see cref="DbContext" />.</summary>
public partial interface IDbContext //: IAsyncDisposable
{
Expand Down
63 changes: 63 additions & 0 deletions src/Extensions/DesignTimeDbContextFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore.SqlServer;

namespace Microsoft.EntityFrameworkCore.Design;

public class DesignTimeDbContextFactory<TContext> : IDesignTimeDbContextFactory<TContext>
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<TContext>()
.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<TContext> Configure(DbContextOptionsBuilder<TContext> 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<TContext>()
.UseSqlServer(
GetConnectionString(configuration)
?? configuration.GetConnectionString("DefaultConnection")
?? "Server=(localdb)\\mssqllocaldb;Database=EFProviders.InMemory;Trusted_Connection=True;MultipleActiveResultSets=true",
x => Configure(x)
))
.Options
) as TContext)!;
}
}
2 changes: 1 addition & 1 deletion src/Extensions/Dgmjr.EntityFrameworkCore.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<PackageReference Include="Dgmjr.InterfaceGenerator" IncludeAssets="Analyzers;Build" ExcludeAssets="Native;BuildTransitive;BuildMultitargeting;ContentFiles;Compile;Runtime" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="Dgmjr.Abstractions" />
<PackageReference Include="Dgmjr.System.Extensions" VersionOverride="0.0.1-Local" />
<PackageReference Include="Dgmjr.System.Extensions" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
Expand Down
11 changes: 11 additions & 0 deletions src/Migrations/CreateViewOperation.cs
Original file line number Diff line number Diff line change
@@ -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);
1 change: 1 addition & 0 deletions src/Models/Dgmjr.EntityFrameworkCore.Models.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<PackageReference Include="System.Collections.Generic.Usings" IncludeAssets="Build;BuildTransitive;BuildMultitargeting;Runtime;Compile" ExcludeAssets="ContentFiles;Native;Analyzers" PrivateAssets="None" />
<PackageReference Include="System.ComponentModel.Usings" IncludeAssets="Build;BuildTransitive;BuildMultitargeting;Runtime;Compile" ExcludeAssets="ContentFiles;Native;Analyzers" PrivateAssets="None" />
<!-- <PackageReference Include="System.Runtime" Condition="$(TargetFramework.Contains('netstandard'))" /> -->
<PackageReference Include="Vogen" />
</ItemGroup>
<ItemGroup>
<Using Include="Dgmjr.EntityFrameworkCore.Abstractions" />
Expand Down
72 changes: 72 additions & 0 deletions src/Models/Slug.cs
Original file line number Diff line number Diff line change
@@ -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<Slug>, IEquatable<Slug>, 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<Slug, string>
{
public SlugEfCoreConverter() : this(null) { }
public SlugEfCoreConverter(ConverterMappingHints? mappingHints = null)
: base(v => v.Value, v => v.ToSlug(), mappingHints) { }
}

public class SlugJsonConverter : JsonConverter<Slug>
{
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<TEntity> : IEntityTypeConfiguration<TEntity>
where TEntity : class, IIdentifiable<Slug>
{
public void Configure(EntityTypeBuilder<TEntity> 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();
}

0 comments on commit 011e24d

Please sign in to comment.