From Microsoft SQL Server 2025 (17.x) which is already available in Preview, we now have a new Data Type: json.
EF Core 10.0 now fully supports the json data type.
Consider the following Model.
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public required Contact Contact { get; set; }
}
public class Contact
{
public required Address Address { get; set; }
public List<PhoneNumber> PhoneNumbers { get; set; } = [];
}
public class Address
{
public required string Street { get; set; }
public required string City { get; set; }
public required string State { get; set; }
public required string PostalCode { get; set; }
}
public class PhoneNumber
{
public PhoneNumberType Type { get; set; }
public string Number { get; set; }
public PhoneNumber(PhoneNumberType type, string number)
{
Type = type;
Number = number;
}
}
public enum PhoneNumberType
{
Mobile,
Home
}
And I have configured the MyDbContext as follows.
public class MyDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer("<SqlServer2025_ConnectionString>", x =>
{
x.UseCompatibilityLevel(170);
});
}
override protected void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Customer>(x =>
{
x.ComplexProperty(x => x.Contact, x => x.ToJson());
});
}
}
Note the ComplexProperty(). For more information on ComplexProperty(), read a previous post: EF Core 10.0: Support for Complex Types without using Owned Entities for more information.
When configured to target Microsoft SQL Server 2025, EF Core 10.0 creates the following table for the above.
CREATE TABLE [Customers] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NOT NULL,
[Contact] json NOT NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY ([Id])
);
|
Data Type: json |
Querying
We can do queries on JSON data, for example, consider the following.
List<Customer> customersInWA = await context.Customers
.Where(x => x.Contact.Address.State == "WA")
.ToListAsync();
The generated SQL statements will be as follows.
SELECT [c].[Id], [c].[Name], [c].[Contact]
FROM [Customers] AS [c]
WHERE JSON_VALUE([c].[Contact], '$.Address.State' RETURNING nvarchar(max)) = N'WA'
Projection
List<string> distinctStates = await context.Customers
.Select(x => x.Contact.Address.State)
.Distinct()
.ToListAsync();
The generated SQL statement:
SELECT DISTINCT JSON_VALUE([c].[Contact], '$.Address.State' RETURNING nvarchar(max))
FROM [Customers] AS [c]
Update
Customer customerToUpdate = await context.Customers.SingleAsync(x => x.Name == "Jane Doe");
customerToUpdate.Contact.Address.PostalCode = "97202";
await context.SaveChangesAsync();
Here the generated SQL statement:
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [Customers] SET [Contact] = @p0
OUTPUT 1
WHERE [Id] = @p1;
However, I'd expect it be something like below:
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [Customers] SET [Contact] = JSON_MODIFY([Contact], 'strict $.Address.PostalCode', JSON_VALUE(@p0, '$[0]'))
OUTPUT 1
WHERE [Id] = @p1;
Created an issue: dotnet/efcore/issues/36732
It's getting nicer and exciting everyday.
Read more:
What's New in EF Core 10
Happy Coding.
Regards,
Jaliya
No comments:
Post a Comment