Skip to content

Commit 81c4e5d

Browse files
committed
.Net 10
1 parent 3222e36 commit 81c4e5d

4 files changed

Lines changed: 188 additions & 7 deletions

File tree

src/EntityFrameworkCore.SqlServer.SimpleBulks.Tests/Database/TestDbContext.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
6565
{
6666
x.ToJson();
6767
//x.ToJson("xxx").HasColumnType("json");
68-
//x.ComplexProperty(y => y.Location, y =>
69-
//{
70-
// y.ToJson();
71-
// //y.ToJson("xxx").HasColumnType("json");
72-
//});
68+
x.ComplexProperty(y => y.Location, y =>
69+
{
70+
y.HasJsonPropertyName("xxx");
71+
});
7372
});
7473

7574
base.OnModelCreating(modelBuilder);

src/EntityFrameworkCore.SqlServer.SimpleBulks.Tests/DbContextExtensions/GetPropertiesTests.cs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using EntityFrameworkCore.SqlServer.SimpleBulks.Extensions;
22
using EntityFrameworkCore.SqlServer.SimpleBulks.Tests.Database;
33
using Microsoft.EntityFrameworkCore.Metadata;
4+
using System.Text;
5+
using System.Text.Json;
46

57
namespace EntityFrameworkCore.SqlServer.SimpleBulks.Tests.DbContextExtensions;
68

@@ -282,5 +284,96 @@ public void GetProperties_JsonComplexType_ReturnsCorrectColumnInformation()
282284
Assert.False(property.IsPrimaryKey);
283285
Assert.False(property.IsRowVersion);
284286
Assert.True(property.IsJson);
287+
Assert.NotNull(property.JsonPropertyWriters);
288+
289+
// Verify that the JsonPropertyWriters have correct structure
290+
var writers = property.JsonPropertyWriters;
291+
Assert.Equal(2, writers.Count); // Street and Location
292+
293+
var streetWriter = writers.FirstOrDefault(w => w.ClrPropertyName == "Street");
294+
Assert.NotNull(streetWriter);
295+
Assert.Equal("Street", streetWriter.JsonPropertyName);
296+
Assert.Equal(typeof(string), streetWriter.PropertyType);
297+
Assert.False(streetWriter.IsNestedComplexType);
298+
299+
var locationWriter = writers.FirstOrDefault(w => w.ClrPropertyName == "Location");
300+
Assert.NotNull(locationWriter);
301+
Assert.Equal("xxx", locationWriter.JsonPropertyName); // Mapped to "xxx" in TestDbContext
302+
Assert.Equal(typeof(ComplexTypeLocation), locationWriter.PropertyType);
303+
Assert.True(locationWriter.IsNestedComplexType);
304+
Assert.NotNull(locationWriter.NestedProperties);
305+
Assert.Equal(2, locationWriter.NestedProperties.Count); // Lat and Lng
306+
307+
var latWriter = locationWriter.NestedProperties.FirstOrDefault(w => w.ClrPropertyName == "Lat");
308+
Assert.NotNull(latWriter);
309+
Assert.Equal(typeof(double), latWriter.PropertyType);
310+
311+
var lngWriter = locationWriter.NestedProperties.FirstOrDefault(w => w.ClrPropertyName == "Lng");
312+
Assert.NotNull(lngWriter);
313+
Assert.Equal(typeof(double), lngWriter.PropertyType);
314+
315+
// Verify serialization using JsonPropertyWriters
316+
var testAddress = new ComplexTypeAddress
317+
{
318+
Street = "123 Main St",
319+
Location = new ComplexTypeLocation
320+
{
321+
Lat = 40.7128,
322+
Lng = -74.0060
323+
}
324+
};
325+
326+
var json = SerializeWithJsonPropertyWriters(testAddress, writers);
327+
Assert.NotNull(json);
328+
Assert.Contains("Street", json);
329+
Assert.Contains("123 Main St", json);
330+
Assert.Contains("xxx", json); // Location is mapped to "xxx"
331+
Assert.Contains("Lat", json);
332+
Assert.Contains("Lng", json);
333+
}
334+
335+
private static string SerializeWithJsonPropertyWriters(object obj, IReadOnlyList<JsonPropertyWriter> writers)
336+
{
337+
using var stream = new MemoryStream();
338+
using var writer = new Utf8JsonWriter(stream);
339+
340+
WriteObject(writer, obj, writers);
341+
342+
writer.Flush();
343+
return Encoding.UTF8.GetString(stream.ToArray());
344+
}
345+
346+
private static void WriteObject(Utf8JsonWriter writer, object obj, IReadOnlyList<JsonPropertyWriter> propertyWriters)
347+
{
348+
writer.WriteStartObject();
349+
350+
var type = obj.GetType();
351+
foreach (var propWriter in propertyWriters)
352+
{
353+
var propInfo = type.GetProperty(propWriter.ClrPropertyName);
354+
if (propInfo == null) continue;
355+
356+
var value = propInfo.GetValue(obj);
357+
358+
writer.WritePropertyName(propWriter.JsonPropertyName);
359+
360+
if (propWriter.IsNestedComplexType)
361+
{
362+
if (value == null)
363+
{
364+
writer.WriteNullValue();
365+
}
366+
else
367+
{
368+
WriteObject(writer, value, propWriter.NestedProperties);
369+
}
370+
}
371+
else
372+
{
373+
propWriter.WriteValue(writer, value);
374+
}
375+
}
376+
377+
writer.WriteEndObject();
285378
}
286379
}

src/EntityFrameworkCore.SqlServer.SimpleBulks/ColumnInfor.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using Microsoft.EntityFrameworkCore.Metadata;
2+
using Microsoft.EntityFrameworkCore.Storage.Json;
23
using System;
4+
using System.Collections.Generic;
5+
using System.Text.Json;
36

47
namespace EntityFrameworkCore.SqlServer.SimpleBulks;
58

@@ -24,4 +27,40 @@ public class ColumnInfor
2427
public ValueConverter? ValueConverter { get; set; }
2528

2629
public bool IsJson { get; set; }
30+
31+
public IReadOnlyList<JsonPropertyWriter>? JsonPropertyWriters { get; init; }
32+
}
33+
34+
public class JsonPropertyWriter
35+
{
36+
public string JsonPropertyName { get; init; }
37+
38+
public string ClrPropertyName { get; init; }
39+
40+
public Type PropertyType { get; init; }
41+
42+
public JsonValueReaderWriter? ReaderWriter { get; init; }
43+
44+
public IReadOnlyList<JsonPropertyWriter>? NestedProperties { get; init; }
45+
46+
public bool IsNestedComplexType => NestedProperties != null && NestedProperties.Count > 0;
47+
48+
public void WriteValue(Utf8JsonWriter writer, object? value)
49+
{
50+
if (value == null)
51+
{
52+
writer.WriteNullValue();
53+
return;
54+
}
55+
56+
if (ReaderWriter != null)
57+
{
58+
ReaderWriter.ToJson(writer, value);
59+
}
60+
else
61+
{
62+
// Fallback to System.Text.Json for types without a specific JsonValueReaderWriter
63+
JsonSerializer.Serialize(writer, value, PropertyType);
64+
}
65+
}
2766
}

src/EntityFrameworkCore.SqlServer.SimpleBulks/Extensions/DbContextExtensions.cs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,14 @@ public static IReadOnlyList<ColumnInfor> GetProperties(this DbContext dbContext,
150150
continue;
151151
}
152152

153-
AddOwnedProperty(data, ownedProperty.TargetEntityType, tableId, ownedProperty.Name + ".");
153+
if (ownedProperty.TargetEntityType.IsMappedToJson())
154+
{
155+
156+
}
157+
else
158+
{
159+
AddOwnedProperty(data, ownedProperty.TargetEntityType, tableId, ownedProperty.Name + ".");
160+
}
154161
}
155162

156163
return data;
@@ -185,6 +192,9 @@ private static void AddJsonComplexProperty(List<ColumnInfor> columnInfors, IComp
185192
var containerColumnName = complexProperty.ComplexType.GetContainerColumnName();
186193
var containerColumnType = complexProperty.ComplexType.GetContainerColumnType() ?? "nvarchar(max)";
187194

195+
// Build JsonPropertyWriters using EF Core's GetJsonValueReaderWriter for each property
196+
var jsonPropertyWriters = BuildJsonPropertyWriters(complexProperty.ComplexType);
197+
188198
columnInfors.Add(new ColumnInfor
189199
{
190200
PropertyName = complexProperty.Name,
@@ -196,10 +206,50 @@ private static void AddJsonComplexProperty(List<ColumnInfor> columnInfors, IComp
196206
IsPrimaryKey = false,
197207
IsRowVersion = false,
198208
ValueConverter = null,
199-
IsJson = true
209+
IsJson = true,
210+
JsonPropertyWriters = jsonPropertyWriters
200211
});
201212
}
202213

214+
private static List<JsonPropertyWriter> BuildJsonPropertyWriters(IComplexType complexType)
215+
{
216+
var writers = new List<JsonPropertyWriter>();
217+
218+
// Add writers for scalar properties
219+
foreach (var property in complexType.GetProperties())
220+
{
221+
var jsonPropertyName = property.GetJsonPropertyName() ?? property.Name;
222+
var readerWriter = property.GetJsonValueReaderWriter() ?? property.GetTypeMapping().JsonValueReaderWriter;
223+
224+
writers.Add(new JsonPropertyWriter
225+
{
226+
JsonPropertyName = jsonPropertyName,
227+
ClrPropertyName = property.Name,
228+
PropertyType = property.ClrType,
229+
ReaderWriter = readerWriter,
230+
NestedProperties = null
231+
});
232+
}
233+
234+
// Add writers for nested complex properties
235+
foreach (var nestedComplexProperty in complexType.GetComplexProperties())
236+
{
237+
var jsonPropertyName = nestedComplexProperty.GetJsonPropertyName() ?? nestedComplexProperty.Name;
238+
var nestedWriters = BuildJsonPropertyWriters(nestedComplexProperty.ComplexType);
239+
240+
writers.Add(new JsonPropertyWriter
241+
{
242+
JsonPropertyName = jsonPropertyName,
243+
ClrPropertyName = nestedComplexProperty.Name,
244+
PropertyType = nestedComplexProperty.ClrType,
245+
ReaderWriter = null,
246+
NestedProperties = nestedWriters
247+
});
248+
}
249+
250+
return writers;
251+
}
252+
203253
private static void AddComplexProperty(List<ColumnInfor> columnInfors, IComplexProperty complexProperty, StoreObjectIdentifier storeObjectIdentifier, string prefix = "")
204254
{
205255
var entityProperties = complexProperty.ComplexType.GetProperties();

0 commit comments

Comments
 (0)