Skip to content

Commit 80ca084

Browse files
authored
Merge branch 'main' into codeql
2 parents b21c092 + f2fe183 commit 80ca084

File tree

12 files changed

+311
-22
lines changed

12 files changed

+311
-22
lines changed

MADE.NET.sln

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MADE.Data.Serialization", "
5151
EndProject
5252
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MADE.Data.Serialization.Tests", "tests\MADE.Data.Serialization.Tests\MADE.Data.Serialization.Tests.csproj", "{7D789D04-A010-4F11-91AD-B1B94A23BAE0}"
5353
EndProject
54+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MADE.Data.EFCore.Tests", "tests\MADE.Data.EFCore.Tests\MADE.Data.EFCore.Tests.csproj", "{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}"
55+
EndProject
5456
Global
5557
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5658
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -1315,6 +1317,62 @@ Global
13151317
{7D789D04-A010-4F11-91AD-B1B94A23BAE0}.Release|x64.Build.0 = Release|Any CPU
13161318
{7D789D04-A010-4F11-91AD-B1B94A23BAE0}.Release|x86.ActiveCfg = Release|Any CPU
13171319
{7D789D04-A010-4F11-91AD-B1B94A23BAE0}.Release|x86.Build.0 = Release|Any CPU
1320+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
1321+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
1322+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
1323+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
1324+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|ARM64.ActiveCfg = Debug|Any CPU
1325+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|ARM64.Build.0 = Debug|Any CPU
1326+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
1327+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
1328+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
1329+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
1330+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
1331+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
1332+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
1333+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
1334+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
1335+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|Any CPU.Build.0 = Debug|Any CPU
1336+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|ARM.ActiveCfg = Debug|Any CPU
1337+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|ARM.Build.0 = Debug|Any CPU
1338+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|ARM64.ActiveCfg = Debug|Any CPU
1339+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|ARM64.Build.0 = Debug|Any CPU
1340+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
1341+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|iPhone.Build.0 = Debug|Any CPU
1342+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
1343+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
1344+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|x64.ActiveCfg = Debug|Any CPU
1345+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|x64.Build.0 = Debug|Any CPU
1346+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|x86.ActiveCfg = Debug|Any CPU
1347+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.AppStore|x86.Build.0 = Debug|Any CPU
1348+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1349+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|Any CPU.Build.0 = Debug|Any CPU
1350+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|ARM.ActiveCfg = Debug|Any CPU
1351+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|ARM.Build.0 = Debug|Any CPU
1352+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|ARM64.ActiveCfg = Debug|Any CPU
1353+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|ARM64.Build.0 = Debug|Any CPU
1354+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|iPhone.ActiveCfg = Debug|Any CPU
1355+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|iPhone.Build.0 = Debug|Any CPU
1356+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
1357+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
1358+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|x64.ActiveCfg = Debug|Any CPU
1359+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|x64.Build.0 = Debug|Any CPU
1360+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|x86.ActiveCfg = Debug|Any CPU
1361+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Debug|x86.Build.0 = Debug|Any CPU
1362+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|Any CPU.ActiveCfg = Release|Any CPU
1363+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|Any CPU.Build.0 = Release|Any CPU
1364+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|ARM.ActiveCfg = Release|Any CPU
1365+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|ARM.Build.0 = Release|Any CPU
1366+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|ARM64.ActiveCfg = Release|Any CPU
1367+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|ARM64.Build.0 = Release|Any CPU
1368+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|iPhone.ActiveCfg = Release|Any CPU
1369+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|iPhone.Build.0 = Release|Any CPU
1370+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
1371+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
1372+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|x64.ActiveCfg = Release|Any CPU
1373+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|x64.Build.0 = Release|Any CPU
1374+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|x86.ActiveCfg = Release|Any CPU
1375+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413}.Release|x86.Build.0 = Release|Any CPU
13181376
EndGlobalSection
13191377
GlobalSection(SolutionProperties) = preSolution
13201378
HideSolutionNode = FALSE
@@ -1342,6 +1400,7 @@ Global
13421400
{D8C1B3CC-B5BA-4946-944E-D898AB4DFF6E} = {69149D0F-BB09-411B-88F0-A1E845058D70}
13431401
{0ACCC377-5FA5-47D9-B6EF-7936F1038B90} = {01380FB8-F8A7-4416-AABA-5407574B7723}
13441402
{7D789D04-A010-4F11-91AD-B1B94A23BAE0} = {69149D0F-BB09-411B-88F0-A1E845058D70}
1403+
{7ECFE1EE-A42A-495E-BBB1-A34C95F70413} = {69149D0F-BB09-411B-88F0-A1E845058D70}
13451404
EndGlobalSection
13461405
GlobalSection(ExtensibilityGlobals) = postSolution
13471406
SolutionGuid = {3921AD86-E6C0-4436-8880-2D9EDFAD6151}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// MADE Apps licenses this file to you under the MIT license.
2+
// See the LICENSE file in the project root for more information.
3+
4+
namespace MADE.Data.EFCore
5+
{
6+
using System;
7+
using System.ComponentModel.DataAnnotations.Schema;
8+
9+
/// <summary>
10+
/// Defines a base definition for an entity.
11+
/// </summary>
12+
/// <typeparam name="TKey">The type of unique identifier for the entity.</typeparam>
13+
public abstract class EntityBase<TKey> : IEntityBase<TKey>
14+
{
15+
/// <summary>
16+
/// Gets or sets the identifier of the entity.
17+
/// </summary>
18+
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
19+
public TKey Id { get; set; }
20+
21+
/// <summary>
22+
/// Gets or sets the date of the entity's creation.
23+
/// </summary>
24+
public DateTime CreatedDate { get; set; }
25+
26+
/// <summary>
27+
/// Gets or sets the date of the entity's last update.
28+
/// </summary>
29+
public DateTime? UpdatedDate { get; set; }
30+
}
31+
}

src/MADE.Data.EFCore/Extensions/DbContextExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ public static void SetEntityDates(this DbContext context)
6464
IEnumerable<EntityEntry> entries = context.ChangeTracker
6565
.Entries()
6666
.Where(
67-
entry => entry.Entity is IEntityBase &&
67+
entry => entry.Entity is IDatedEntity &&
6868
entry.State is EntityState.Added or EntityState.Modified);
6969

7070
DateTime now = DateTime.UtcNow;
7171

7272
foreach (EntityEntry entry in entries)
7373
{
74-
var entity = (IEntityBase)entry.Entity;
74+
var entity = (IDatedEntity)entry.Entity;
7575
entity.UpdatedDate = now;
7676

7777
if (entry.State == EntityState.Added && entity.CreatedDate == DateTime.MinValue)

src/MADE.Data.EFCore/Extensions/EntityBaseExtensions.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace MADE.Data.EFCore.Extensions
55
{
6+
using System;
67
using MADE.Data.EFCore.Converters;
78
using Microsoft.EntityFrameworkCore.Metadata.Builders;
89

@@ -19,6 +20,20 @@ public static class EntityBaseExtensions
1920
/// <returns>The entity type builder.</returns>
2021
public static EntityTypeBuilder<TEntity> Configure<TEntity>(this EntityTypeBuilder<TEntity> builder)
2122
where TEntity : class, IEntityBase
23+
{
24+
builder.ConfigureWithKey<TEntity, Guid>();
25+
return builder;
26+
}
27+
28+
/// <summary>
29+
/// Configures the default properties of an <typeparamref name="TEntity">entity</typeparamref>.
30+
/// </summary>
31+
/// <typeparam name="TEntity">The type of entity to configure.</typeparam>
32+
/// <typeparam name="TKey">The type of unique identifier for the entity.</typeparam>
33+
/// <param name="builder">The entity type builder associated with the entity.</param>
34+
/// <returns>The entity type builder.</returns>
35+
public static EntityTypeBuilder<TEntity> ConfigureWithKey<TEntity, TKey>(this EntityTypeBuilder<TEntity> builder)
36+
where TEntity : class, IEntityBase<TKey>
2237
{
2338
builder.HasKey(e => e.Id);
2439
builder.ConfigureDateProperties();
@@ -33,7 +48,7 @@ public static EntityTypeBuilder<TEntity> Configure<TEntity>(this EntityTypeBuild
3348
/// <returns>The entity type builder.</returns>
3449
public static EntityTypeBuilder<TEntity> ConfigureDateProperties<TEntity>(
3550
this EntityTypeBuilder<TEntity> builder)
36-
where TEntity : class, IEntityBase
51+
where TEntity : class, IDatedEntity
3752
{
3853
builder.Property(x => x.CreatedDate).IsUtc();
3954
builder.Property(x => x.UpdatedDate).IsUtc();

src/MADE.Data.EFCore/Extensions/QueryableExtensions.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ public static IQueryable<T> Page<T>(this IQueryable<T> query, int page, int page
3434
/// <returns>The ordered query.</returns>
3535
public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string sortName, bool sortDesc)
3636
{
37-
return string.IsNullOrWhiteSpace(sortName)
38-
? query
39-
: (!sortDesc ? query.AddOrAppendOrderBy(sortName) : query.AddOrAppendOrderByDescending(sortName));
37+
if (string.IsNullOrWhiteSpace(sortName))
38+
{
39+
return query;
40+
}
41+
42+
return !sortDesc ? query.AddOrAppendOrderBy(sortName) : query.AddOrAppendOrderByDescending(sortName);
4043
}
4144
}
4245
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// MADE Apps licenses this file to you under the MIT license.
2+
// See the LICENSE file in the project root for more information.
3+
4+
namespace MADE.Data.EFCore
5+
{
6+
using System;
7+
8+
/// <summary>
9+
/// Defines a base definition for an entity with defined created and updated date.
10+
/// </summary>
11+
public interface IDatedEntity
12+
{
13+
/// <summary>
14+
/// Gets or sets the date of the entity's creation.
15+
/// </summary>
16+
DateTime CreatedDate { get; set; }
17+
18+
/// <summary>
19+
/// Gets or sets the date of the entity's last update.
20+
/// </summary>
21+
DateTime? UpdatedDate { get; set; }
22+
}
23+
}

src/MADE.Data.EFCore/IEntityBase.cs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,7 @@ namespace MADE.Data.EFCore
88
/// <summary>
99
/// Defines a base definition for an entity.
1010
/// </summary>
11-
public interface IEntityBase
11+
public interface IEntityBase : IEntityBase<Guid>
1212
{
13-
/// <summary>
14-
/// Gets or sets the identifier of the entity.
15-
/// </summary>
16-
Guid Id { get; set; }
17-
18-
/// <summary>
19-
/// Gets or sets the date of the entity's creation.
20-
/// </summary>
21-
DateTime CreatedDate { get; set; }
22-
23-
/// <summary>
24-
/// Gets or sets the date of the entity's last update.
25-
/// </summary>
26-
DateTime? UpdatedDate { get; set; }
2713
}
2814
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// MADE Apps licenses this file to you under the MIT license.
2+
// See the LICENSE file in the project root for more information.
3+
4+
namespace MADE.Data.EFCore
5+
{
6+
/// <summary>
7+
/// Defines a base definition for an entity with a defined primary key type.
8+
/// </summary>
9+
/// <typeparam name="TKey">The type of unique identifier for the entity.</typeparam>
10+
public interface IEntityBase<TKey> : IDatedEntity
11+
{
12+
/// <summary>
13+
/// Gets or sets the identifier of the entity.
14+
/// </summary>
15+
TKey Id { get; set; }
16+
}
17+
}

src/MADE.Data.Validation.FluentValidation/MADE.Data.Validation.FluentValidation.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="FluentValidation" Version="11.2.0" />
15+
<PackageReference Include="FluentValidation" Version="11.2.1" />
1616
</ItemGroup>
1717

1818
<ItemGroup>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
namespace MADE.Data.EFCore.Tests.Data
2+
{
3+
using System.Diagnostics.CodeAnalysis;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Converters;
7+
using Extensions;
8+
using Microsoft.EntityFrameworkCore;
9+
using Microsoft.EntityFrameworkCore.Metadata.Builders;
10+
11+
[ExcludeFromCodeCoverage]
12+
public class TestDbContext : DbContext
13+
{
14+
public DbSet<TestEntity> Entities { get; set; }
15+
16+
public DbSet<TestKeyedEntity> KeyEntities { get; set; }
17+
18+
public TestDbContext(DbContextOptions<TestDbContext> options) : base(options) { }
19+
20+
public static TestDbContext CreateInMemoryContext(string dbName)
21+
{
22+
var optionsBuilder = new DbContextOptionsBuilder<TestDbContext>();
23+
DbContextOptions<TestDbContext> options = optionsBuilder.UseInMemoryDatabase(dbName).Options;
24+
return new TestDbContext(options);
25+
}
26+
27+
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
28+
{
29+
this.SetEntityDates();
30+
return base.SaveChangesAsync(cancellationToken);
31+
}
32+
33+
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
34+
{
35+
this.SetEntityDates();
36+
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
37+
}
38+
39+
protected override void OnModelCreating(ModelBuilder modelBuilder)
40+
{
41+
modelBuilder.HasDefaultSchema("dbo");
42+
modelBuilder.ApplyConfigurationsFromAssembly(typeof(TestDbContext).Assembly);
43+
modelBuilder.ApplyUtcDateTimeConverter();
44+
}
45+
}
46+
47+
public class TestEntity : EntityBase
48+
{
49+
public string Name { get; set; }
50+
}
51+
52+
public class TestKeyedEntity : EntityBase<int>
53+
{
54+
public string Name { get; set; }
55+
}
56+
57+
public class TestEntityTypeConfiguration : IEntityTypeConfiguration<TestEntity>
58+
{
59+
public void Configure(EntityTypeBuilder<TestEntity> builder)
60+
{
61+
builder.Configure();
62+
}
63+
}
64+
65+
public class TestKeyedEntityTypeConfiguration : IEntityTypeConfiguration<TestKeyedEntity>
66+
{
67+
public void Configure(EntityTypeBuilder<TestKeyedEntity> builder)
68+
{
69+
builder.ConfigureWithKey<TestKeyedEntity, int>();
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)