Skip to content

Commit fc7d28b

Browse files
authored
Adds AutoHistory for logging DB changes automatically (#1389)
* add autohistory nuget package and configure it properly * add user id to autohistory * use the proper autohistory package * exclude all entities from autohistory for now * enable autohistory for game and gameversion * add autohistory migration
1 parent 1f31e70 commit fc7d28b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+3982
-47
lines changed

NuGet.Config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
<packageSources>
44
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
55
<add key="Pomelo" value="https://www.myget.org/F/pomelo/api/v3/index.json" />
6+
<add key="Custom Packages" value="custompackages" />
67
</packageSources>
78
</configuration>

TASVideos.Core/Services/SignInManager.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using Microsoft.EntityFrameworkCore;
77
using Microsoft.Extensions.Logging;
88
using Microsoft.Extensions.Options;
9-
using TASVideos.Core.Extensions;
109
using TASVideos.Data;
1110
using TASVideos.Data.Entity;
1211

TASVideos.Data/ApplicationDbContext.cs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHtt
2727
_httpContext = httpContextAccessor;
2828
}
2929

30+
public DbSet<AutoHistory> AutoHistory { get; set; } = null!;
31+
3032
public DbSet<RolePermission> RolePermission { get; set; } = null!;
3133
public DbSet<WikiPage> WikiPages { get; set; } = null!;
3234
public DbSet<WikiPageReferral> WikiReferrals { get; set; } = null!;
@@ -94,16 +96,65 @@ public override int SaveChanges(bool acceptAllChangesOnSuccess)
9496
PerformTrackingUpdates();
9597

9698
ChangeTracker.AutoDetectChangesEnabled = false;
99+
100+
// remember added entries,
101+
// before EF Core is assigning valid Ids (it does on save changes,
102+
// when ids equal zero) and setting their state to
103+
// Unchanged (it does on every save changes)
104+
var addedEntities = ChangeTracker
105+
.Entries()
106+
.Where(e => e.State == EntityState.Added)
107+
.ToArray();
108+
109+
this.EnsureAutoHistory(() => new CustomAutoHistory()
110+
{
111+
UserId = _httpContext?.HttpContext?.User.GetUserId() ?? -1
112+
});
97113
var result = base.SaveChanges(acceptAllChangesOnSuccess);
114+
115+
// after "SaveChanges" added enties now have gotten valid ids (if it was necessary)
116+
// and the history for them can be ensured and be saved with another "SaveChanges"
117+
this.EnsureAddedHistory(
118+
() => new CustomAutoHistory()
119+
{
120+
UserId = _httpContext?.HttpContext?.User.GetUserId() ?? -1
121+
}, addedEntities);
122+
result += base.SaveChanges(acceptAllChangesOnSuccess);
123+
98124
ChangeTracker.AutoDetectChangesEnabled = true;
99125

100126
return result;
101127
}
102128

103-
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
129+
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
104130
{
105131
PerformTrackingUpdates();
106-
return base.SaveChangesAsync(cancellationToken);
132+
133+
// remember added entries,
134+
// before EF Core is assigning valid Ids (it does on save changes,
135+
// when ids equal zero) and setting their state to
136+
// Unchanged (it does on every save changes)
137+
var addedEntities = ChangeTracker
138+
.Entries()
139+
.Where(e => e.State == EntityState.Added)
140+
.ToArray();
141+
142+
this.EnsureAutoHistory(() => new CustomAutoHistory()
143+
{
144+
UserId = _httpContext?.HttpContext?.User.GetUserId() ?? -1
145+
});
146+
var result = await base.SaveChangesAsync(cancellationToken);
147+
148+
// after "SaveChanges" added enties now have gotten valid ids (if it was necessary)
149+
// and the history for them can be ensured and be saved with another "SaveChanges"
150+
this.EnsureAddedHistory(
151+
() => new CustomAutoHistory()
152+
{
153+
UserId = _httpContext?.HttpContext?.User.GetUserId() ?? -1
154+
}, addedEntities);
155+
result += await base.SaveChangesAsync(CancellationToken.None);
156+
157+
return result;
107158
}
108159

109160
/// <summary>
@@ -421,6 +472,11 @@ protected override void OnModelCreating(ModelBuilder builder)
421472
{
422473
entity.HasIndex(e => e.FileExtension).IsUnique();
423474
});
475+
476+
builder.EnableAutoHistory<CustomAutoHistory>(o =>
477+
{
478+
o.LimitChangedLength = false;
479+
});
424480
}
425481

426482
private void PerformTrackingUpdates()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace TASVideos.Data;
4+
5+
internal class CustomAutoHistory : AutoHistory
6+
{
7+
public int UserId { get; set; }
8+
}

TASVideos.Data/Entity/Awards/Award.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
namespace TASVideos.Data.Entity.Awards;
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace TASVideos.Data.Entity.Awards;
24

35
public enum AwardType
46
{
57
User = 1,
68
Movie
79
}
810

11+
[ExcludeFromHistory]
912
public class Award
1013
{
1114
public int Id { get; set; }

TASVideos.Data/Entity/Awards/PublicationAward.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
namespace TASVideos.Data.Entity.Awards;
1+
using Microsoft.EntityFrameworkCore;
22

3+
namespace TASVideos.Data.Entity.Awards;
4+
5+
[ExcludeFromHistory]
36
public class PublicationAward
47
{
58
public int Id { get; set; }

TASVideos.Data/Entity/Awards/UserAward.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
namespace TASVideos.Data.Entity.Awards;
1+
using Microsoft.EntityFrameworkCore;
22

3+
namespace TASVideos.Data.Entity.Awards;
4+
5+
[ExcludeFromHistory]
36
public class UserAward
47
{
58
public int Id { get; set; }

TASVideos.Data/Entity/BaseEntity.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace TASVideos.Data.Entity;
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace TASVideos.Data.Entity;
24

35
public interface ITrackable
46
{
@@ -11,10 +13,14 @@ public interface ITrackable
1113

1214
public class BaseEntity : ITrackable
1315
{
16+
[ExcludeFromHistory]
1417
public DateTime CreateTimestamp { get; set; }
18+
[ExcludeFromHistory]
1519
public string? CreateUserName { get; set; }
1620

21+
[ExcludeFromHistory]
1722
public DateTime LastUpdateTimestamp { get; set; }
23+
[ExcludeFromHistory]
1824
public string? LastUpdateUserName { get; set; }
1925
}
2026

TASVideos.Data/Entity/DeprecatedMovieFormat.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
namespace TASVideos.Data.Entity;
1+
using Microsoft.EntityFrameworkCore;
22

3+
namespace TASVideos.Data.Entity;
4+
5+
[ExcludeFromHistory]
36
public class DeprecatedMovieFormat : BaseEntity
47
{
58
public int Id { get; set; }

TASVideos.Data/Entity/Flag.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
namespace TASVideos.Data.Entity;
1+
using Microsoft.EntityFrameworkCore;
22

3+
namespace TASVideos.Data.Entity;
4+
5+
[ExcludeFromHistory]
36
public class Flag : BaseEntity
47
{
58
public int Id { get; set; }

0 commit comments

Comments
 (0)