Skip to content

Commit df214d8

Browse files
authored
Handle SmartEnum properties (#76)
* Update dependencies * Handle converters returning value types (like with SmartEnum) - Fixes #74
1 parent a5b5a0c commit df214d8

11 files changed

Lines changed: 139 additions & 1 deletion

File tree

src/PhenX.EntityFrameworkCore.BulkInsert/Metadata/PropertyAccessor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ internal static class PropertyAccessor
6464
// instance => converter(body)
6565
var invokeConverter = Expression.Invoke(converter, converterInput);
6666

67-
if (body.Type.IsClass)
67+
// If the property is a reference type, we need to check for null before calling the converter
68+
if (body.Type.IsClass && !invokeConverter.Type.IsValueType)
6869
{
6970
// instance => body == null ? null : converter(body)
7071
var nullCondition = Expression.Equal(body, Expression.Constant(null, body.Type));

tests/PhenX.EntityFrameworkCore.BulkInsert.Tests/DbContext/TestDbContext.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Microsoft.EntityFrameworkCore;
22
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
33

4+
using SmartEnum.EFCore;
5+
46
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
57

68
public class TestDbContext : TestDbContextBase
@@ -11,13 +13,16 @@ public class TestDbContext : TestDbContextBase
1113
public DbSet<TestEntityWithGuidId> TestEntitiesWithGuidId { get; set; } = null!;
1214
public DbSet<TestEntityWithConverters> TestEntitiesWithConverter { get; set; } = null!;
1315
public DbSet<TestEntityWithComplexType> TestEntitiesWithComplexType { get; set; } = null!;
16+
public DbSet<TestEntityWithSmartEnum> TestEntitiesWithSmartEnum { get; set; } = null!;
1417
public DbSet<Student> Students { get; set; } = null!;
1518
public DbSet<Course> Courses { get; set; } = null!;
1619

1720
protected override void OnModelCreating(ModelBuilder modelBuilder)
1821
{
1922
base.OnModelCreating(modelBuilder);
2023

24+
modelBuilder.ConfigureSmartEnum();
25+
2126
modelBuilder.Entity<TestEntityWithConverters>(builder =>
2227
{
2328
builder.Property(e => e.CreatedAt)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
4+
5+
[PrimaryKey(nameof(Id))]
6+
public class TestEntityWithSmartEnum : TestEntityBase
7+
{
8+
public int Id { get; set; }
9+
10+
public TestSmartEnum Enum { get; set; } = null!;
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Ardalis.SmartEnum;
2+
3+
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
4+
5+
public class TestSmartEnum : SmartEnum<TestSmartEnum>
6+
{
7+
private TestSmartEnum(string name, int value) : base(name, value)
8+
{
9+
}
10+
11+
public static readonly TestSmartEnum Value = new TestSmartEnum("test", 1);
12+
}

tests/PhenX.EntityFrameworkCore.BulkInsert.Tests/PhenX.EntityFrameworkCore.BulkInsert.Tests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql.NetTopologySuite" Version="9.0.0" />
4545
</ItemGroup>
4646

47+
<ItemGroup Label="Specific dependencies">
48+
<PackageReference Include="Ardalis.SmartEnum.EFCore" Version="8.2.0" />
49+
</ItemGroup>
50+
4751
<ItemGroup>
4852
<ProjectReference Include="..\..\src\PhenX.EntityFrameworkCore.BulkInsert.MySql\PhenX.EntityFrameworkCore.BulkInsert.MySql.csproj" />
4953
<ProjectReference Include="..\..\src\PhenX.EntityFrameworkCore.BulkInsert.Oracle\PhenX.EntityFrameworkCore.BulkInsert.Oracle.csproj" />
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using FluentAssertions;
2+
3+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContainer;
4+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
5+
6+
using Xunit;
7+
8+
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.Tests.Various;
9+
10+
public abstract class VariousTestsBase<TDbContext>(TestDbContainer dbContainer) : IAsyncLifetime
11+
where TDbContext : TestDbContext, new()
12+
{
13+
private readonly Guid _run = Guid.NewGuid();
14+
private TDbContext _context = null!;
15+
16+
public async Task InitializeAsync()
17+
{
18+
_context = await dbContainer.CreateContextAsync<TDbContext>("various");
19+
}
20+
21+
public Task DisposeAsync()
22+
{
23+
_context.Dispose();
24+
return Task.CompletedTask;
25+
}
26+
27+
[SkippableTheory]
28+
[CombinatorialData]
29+
public async Task InsertSmartEnumEntities(InsertStrategy strategy)
30+
{
31+
// Arrange
32+
var entities = new List<TestEntityWithSmartEnum>
33+
{
34+
new TestEntityWithSmartEnum { TestRun = _run, Enum = TestSmartEnum.Value},
35+
new TestEntityWithSmartEnum { TestRun = _run, Enum = TestSmartEnum.Value}
36+
};
37+
38+
// Act
39+
var insertedEntities = await _context.InsertWithStrategyAsync(strategy, entities);
40+
41+
// Assert
42+
insertedEntities.Should().BeEquivalentTo(entities,
43+
o => o.RespectingRuntimeTypes().Excluding(e => e.Id));
44+
}
45+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContainer;
2+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
3+
4+
using Xunit;
5+
6+
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.Tests.Various;
7+
8+
[Trait("Category", "MySql")]
9+
[Collection(TestDbContainerMySqlCollection.Name)]
10+
public class VariousTestsMySql(TestDbContainerMySql dbContainer) : VariousTestsBase<TestDbContextMySql>(dbContainer)
11+
{
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContainer;
2+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
3+
4+
using Xunit;
5+
6+
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.Tests.Various;
7+
8+
[Trait("Category", "Oracle")]
9+
[Collection(TestDbContainerOracleCollection.Name)]
10+
public class VariousTestsOracle(TestDbContainerOracle dbContainer) : VariousTestsBase<TestDbContextOracle>(dbContainer)
11+
{
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContainer;
2+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
3+
4+
using Xunit;
5+
6+
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.Tests.Various;
7+
8+
[Trait("Category", "PostgreSql")]
9+
[Collection(TestDbContainerPostgreSqlCollection.Name)]
10+
public class VariousTestsPostgreSql(TestDbContainerPostgreSql dbContainer) : VariousTestsBase<TestDbContextPostgreSql>(dbContainer)
11+
{
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContainer;
2+
using PhenX.EntityFrameworkCore.BulkInsert.Tests.DbContext;
3+
4+
using Xunit;
5+
6+
namespace PhenX.EntityFrameworkCore.BulkInsert.Tests.Tests.Various;
7+
8+
[Trait("Category", "SqlServer")]
9+
[Collection(TestDbContainerSqlServerCollection.Name)]
10+
public class VariousTestsSqlServer(TestDbContainerSqlServer dbContainer) : VariousTestsBase<TestDbContextSqlServer>(dbContainer)
11+
{
12+
}

0 commit comments

Comments
 (0)