using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace EFCore.Conversions { public readonly struct StrongId : IEquatable { public Guid RawValue { get; } public StrongId(Guid rawValue) { RawValue = rawValue; } public bool Equals(StrongId other) => RawValue == other.RawValue; public override bool Equals(object? obj) => obj is StrongId d && Equals(d); public override int GetHashCode() => RawValue.GetHashCode(); public override string ToString() => RawValue.ToString("N"); public static bool operator ==(StrongId left, StrongId right) => left.RawValue == right.RawValue; public static bool operator !=(StrongId left, StrongId right) => left.RawValue != right.RawValue; public static explicit operator Guid(StrongId d) => d.RawValue; public static explicit operator StrongId(Guid d) => new StrongId(d); } class Program : IHostedService { static async Task Main(string[] args) { await Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddDbContext(cfg => cfg.UseSqlServer("Server=localhost,1433;User Id=sa;Password=yourStrong(!)Password;Database=App")); services.AddTransient(); }) .RunConsoleAsync(); } private readonly CoreContext dbContext; public Program(CoreContext dbContext) { this.dbContext = dbContext; } public async Task StartAsync(CancellationToken cancellationToken) { await dbContext.Database.EnsureCreatedAsync(); var g = Guid.NewGuid(); await dbContext.Entities .Where(d => d.Id == new StrongId(g)) .ToListAsync(); } public Task StopAsync(CancellationToken cancellationToken) { return dbContext.Database.EnsureDeletedAsync(); } } public class Entity { public StrongId Id { get; set; } } public class CoreContext : DbContext { public DbSet Entities => Set(); public CoreContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(b => { b.HasKey(e => e.Id); b.Property(e => e.Id) .ValueGeneratedNever() .HasConversion(new StrongIdConverter()); // Or: // .HasConversion( // e => e.RawValue, // e => new StrongId(e)); }); } public class StrongIdConverter : ValueConverter { public StrongIdConverter() : base( e => e.RawValue, e => new StrongId(e), null) { } } } }