I was recently reading updates in the upcoming .NET 10 release. In the changes to Entity Framework, I saw a section labeled 'JSON type support'. This really intrigued me - I've worked with JSON-based databases and enjoyed the flexibility of storing and working with unstructured data. But I always come back to SQL because it fits most of my needs.
Refer to this article for the official comments from Microsoft: Whats New in EF Core 10
The article from Microsoft explains that there has been JSON support in SQL for several versions, but that the JSON was simply stored as plain text. Now with EF 10, we map complex objects as JSON, and then still query them. I had to try it out. So I dove into some code! This example is with SQLite; I wasn't sure it would work with SQLite but it worked! I'll go over my process.
public class Campground
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public string Name { get; set; } = string.Empty;
public DateOnly SeasonStart { get; set; } = DateOnly.FromDateTime(DateTime.Now);
public DateOnly SeasonEnd { get; set; } = DateOnly.FromDateTime(DateTime.Now);
public List<Site> Sites { get; set; } = new List<Site>();
}
public class Site
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public int SiteNumber { get; set; }
public int MaxOccupancy { get; set; }
public bool IsAccessible { get; set; }
public int MaxRVLength { get; set; }
public decimal DailyFee { get; set; }
}
public class DBContext : DbContext
{
public DbSet<Campground> Campgrounds { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=JsonInSQL-Demo.db");
// optionsBuilder.UseSqlServer("Server=localhost;Database=SampleDb;Trusted_Connection=True;Encrypt=False;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// modelBuilder.Entity<Campground>().ComplexProperty(b => b.Sites, b => b.ToJson());
modelBuilder.Entity<Campground>().ComplexCollection(b => b.Sites, b => b.ToJson());
}
}
Notice that the DBContext only defines one entity:
public DbSet<Campground> Campgrounds { get; set; }
In the OnModelCreating method, notice the model builder is used to map the "Sites" list as a "Complex Collection" in the Campground. The end result is that the database only has the campground table and stores the site data as JSON object:
modelBuilder.Entity<Campground>().ComplexCollection(b => b.Sites, b => b.ToJson());
//Get campgrounds with a RV length of at least 39
var suitableCampgrounds = await db.Campgrounds
.Where(cg => cg.Sites.Any(s => s.MaxRVLength >= 39))
.ToListAsync();
I love that we have this flexibility in Entity Framework. Most of the data I work with is structured and should be structured - but I am excited to have this tool as an option for when I will need a little more flexibility.