EF Core+Sqlite如何将自定义实体集合List<T>映射成JSON数组
2026-08-06EF Core 可以将任何IEnumerable<T>属性(其中 T 是基元类型)映射到数据库中的JSON列。如:IEnumerable<int>,ICollection<string> 。但对于自定义实体集合,EF Core将默认新建另一张表做一对多外键关联,而不是映射成JSON数组存入当前表。可以通过使用内置JSON映射或配置值转换器来实现List<T>与JSON列的转换。
代码示例:将List<PinYinMeaning>属性映射为JSON数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class HanziContext:DbContext
{
public DbSet<Hanzi> HanziTable => Set<Hanzi>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=>optionsBuilder.UseSqlite($"Data Source=Hanzi.db");
}
public class Hanzi
{
[Key]
public string Text { get; set; } = "";
public List<PinYinMeaning> PinYinMeanings { get; set; } = [];
}
public class PinYinMeaning
{
public string PinYin { get; set; } = "";
public string Meaning { get; set; } = "";
}
方法1:使用内置JSON映射,无需手写值转换器。在数据库上下文(HanziContext)中重写OnModelCreating方法。
1
2
3
4
5
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Hanzi>()
.OwnsMany(hanzi => hanzi.PinYinMeanings, builder => builder.ToJson());
}
方法2:配置值转换器。在数据库上下文(HanziContext)中重写OnModelCreating方法。
1
2
3
4
5
6
7
8
9
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Hanzi>()
.Property(h => h.PinYinMeanings)
.HasConversion(
v => JsonConvert.SerializeObject(v),
v => JsonConvert.DeserializeObject<List<PinYinMeaning>>(v) ?? new List<PinYinMeaning>()
);
}
注意:方法2中若直接在原列表中修改数据,EF Core无法侦测List内部元素变更,无法更新数据库。如:
1
2
3
var db = new HanziContext();
db.HanziTable.Find("阿").PinYinMeanings[0].Meaning = "another meaning";
db.SaveChanges();//无法更新数据库。
可以复制出整个集合,在其中更改数据后再替换原集合。如:
1
2
3
4
5
6
7
var db = new HanziContext();
var list = db.HanziTable.Find("阿").PinYinMeanings.ToList();
list[0].Meaning = "another meaning";
db.HanziTable.Find("阿").PinYinMeanings = list;
db.SaveChanges();