Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 521ae31dce | |||
| 6be7a0ceed |
@@ -3,6 +3,8 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<!-- HrynCo shared packages -->
|
||||||
|
<PackageVersion Include="HrynCo.Common" Version="1.0.0" />
|
||||||
<!-- Entity Framework Core -->
|
<!-- Entity Framework Core -->
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
|
||||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5" />
|
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5" />
|
||||||
|
|||||||
@@ -14,12 +14,10 @@ public abstract class Entity : Entity<Guid>
|
|||||||
protected Entity()
|
protected Entity()
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid();
|
Id = Guid.NewGuid();
|
||||||
Created = DateTimeOffset.UtcNow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Entity(Guid id)
|
protected Entity(Guid id)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Created = DateTimeOffset.UtcNow;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
namespace HrynCo.DAL.Abstract.Entities;
|
namespace HrynCo.DAL.Abstract.Entities;
|
||||||
|
|
||||||
public interface IEntity<TId> where TId : struct
|
public interface IEntity
|
||||||
{
|
{
|
||||||
TId Id { get; set; }
|
|
||||||
DateTimeOffset Created { get; set; }
|
DateTimeOffset Created { get; set; }
|
||||||
DateTimeOffset? Updated { get; set; }
|
DateTimeOffset? Updated { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IEntity<TId> : IEntity where TId : struct
|
||||||
|
{
|
||||||
|
TId Id { get; set; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace HrynCo.DAL.EF.Converters;
|
||||||
|
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
internal class UtcValueConverter()
|
||||||
|
: ValueConverter<DateTime, DateTime>(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
namespace HrynCo.DAL.EF.Core;
|
||||||
|
|
||||||
|
using HrynCo.Common;
|
||||||
|
using HrynCo.DAL.Abstract.Entities;
|
||||||
|
using HrynCo.DAL.EF.Converters;
|
||||||
|
using HrynCo.DAL.EF.Exceptions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
|
||||||
|
public abstract class BaseDbContext : DbContext
|
||||||
|
{
|
||||||
|
private readonly IClock _clock;
|
||||||
|
|
||||||
|
protected BaseDbContext(DbContextOptions options, IClock clock)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
_clock = clock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int SaveChanges()
|
||||||
|
{
|
||||||
|
ApplyTimestamps();
|
||||||
|
return base.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
ApplyTimestamps();
|
||||||
|
return await base.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyTimestamps()
|
||||||
|
{
|
||||||
|
DateTimeOffset now = _clock.UtcNow;
|
||||||
|
|
||||||
|
foreach (EntityEntry<IEntity> entry in ChangeTracker.Entries<IEntity>())
|
||||||
|
{
|
||||||
|
switch (entry.State)
|
||||||
|
{
|
||||||
|
case EntityState.Added:
|
||||||
|
entry.Entity.Created = now;
|
||||||
|
break;
|
||||||
|
case EntityState.Modified:
|
||||||
|
entry.Entity.Updated = now;
|
||||||
|
break;
|
||||||
|
case EntityState.Detached:
|
||||||
|
case EntityState.Unchanged:
|
||||||
|
case EntityState.Deleted:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnexpectedEntityStateException(entry.State);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
|
||||||
|
{
|
||||||
|
configurationBuilder.Properties<DateTime>().HaveConversion<UtcValueConverter>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
foreach (IMutableForeignKey relationship in modelBuilder.Model.GetEntityTypes()
|
||||||
|
.SelectMany(e => e.GetForeignKeys()))
|
||||||
|
{
|
||||||
|
relationship.DeleteBehavior = DeleteBehavior.Restrict;
|
||||||
|
}
|
||||||
|
|
||||||
|
modelBuilder.ApplyConfigurationsFromAssembly(GetType().Assembly);
|
||||||
|
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace HrynCo.DAL.EF.Exceptions;
|
||||||
|
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public sealed class UnexpectedEntityStateException : Exception
|
||||||
|
{
|
||||||
|
public UnexpectedEntityStateException(EntityState state)
|
||||||
|
: base($"Unexpected entity state: {state}")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="HrynCo.Common" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
|||||||
Reference in New Issue
Block a user