我有一个使用EF Core和Postgres数据库的.NET Core 3.1应用程序。在数据库中,我有一个jsonb列,现在我想把它映射到EF Core中的一组定义良好的类。
jsonb列的内容如下。
{
"entry1": {
"name": "entry1",
"contents": {
"entry1.1": {
"name": "entry1.1"
},
"entry1.2": {
"name": "entry1.2",
"contents": {
"entry1.2.1": {
"name": "entry1.2.1"
}
}
}
}
}
}
在最顶层,它是一个将字符串映射到条目的字典。每个条目都有一个名称,并且可以有内容,这又是一个将字符串映射到条目的字典。
public class Entry
{
public string name { get; set; }
public Dictionary<string, Entry> contents { get; set; }
}
jsonb列本身就是定义在这样的表上。
public class MyTable {
[Column(TypeName = "jsonb")]
public Dictionary<string, Entry> Entries { get; set; }
}
现在的问题是,它根本无法工作。当我用EF Core从数据库中获取一个条目时,"Entries "属性确实包含了一个单键为 "entry1 "的字典,但这个键的值是一个空的 Entry
对象(名称和内容均为空)。
命名和内容都是空的。Npgsql关于将jsonb列映射到POCOs的文档。 并没有解释在这种情况下如何处理字典。我找不到任何在jsonb列中使用顶级字典的例子,所以我不完全确定我的做法是否正确。
我怎样才能正确地布线,使我的jsonb列被映射到Entry对象的字典中?
下面的方法似乎很好用。
class Program
{
static void Main(string[] args)
{
using (var createCtx = new BlogContext())
{
createCtx.Database.EnsureDeleted();
createCtx.Database.EnsureCreated();
createCtx.Blogs.Add(new Blog
{
Entries = new Dictionary<string, Entry>
{
{ "bla", new Entry { Foo = "foo1" }}
}
});
createCtx.SaveChanges();
}
using var ctx = new BlogContext();
var results = ctx.Blogs.Single();
Console.WriteLine(results.Entries["bla"].Foo);
}
}
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b => b.AddConsole().AddFilter("", LogLevel.Information));
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseNpgsql(@"Host=localhost;Database=test;Username=npgsql_tests;Password=npgsql_tests")
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
}
public class Blog
{
public int Id { get; set; }
[Column(TypeName = "jsonb")]
public Dictionary<string, Entry> Entries { get; set; }
}
public class Entry
{
public string Foo { get; set; }
}
在数据库中
test=# select * from "Blogs"
test-# ;
Id | Name | Entries
----+------+--------------------------
1 | | {"bla": {"Foo": "foo1"}}
(1 row)