用Postgres jsonb列的顶级字典映射到POCOs。

问题描述 投票:0回答:1

我有一个使用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对象的字典中?

.net-core entity-framework-core npgsql
1个回答
1
投票

下面的方法似乎很好用。

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)
© www.soinside.com 2019 - 2024. All rights reserved.