EF Core支持使用List的Json

huangapple go评论77阅读模式
英文:

EF Core Json support with List

问题

可以使用EF Core 7的Json支持将Json列表存储在DB列中吗?我尝试过但没有成功。

我有以下这些类(简化版):

public class StateData
{
    public int Id { get; set; }
    public int DemandId { get; set; }
    public List<StateItem>? MenuState { get; set; }
    public int? LastMenuItem { get; set; }
}

public class StateItem
{
    public int SideMenuItemId { get; set; }
    public int StateDataId { get; set; }
    public int Order { get; set; }
    public string Header { get; set; } = null!;
}

以及这个 DbContext

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : base(options)
{
}

public DbSet<StateData> StateData { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new StateDataConfiguration());
}

配置如下:

public class StateDataConfiguration : IEntityTypeConfiguration<StateData>
{
    public void Configure(EntityTypeBuilder<StateData> builder)
    {
        builder.OwnsMany(d => d.MenuState, builder =>
        {
            builder.ToJson();
        });
    }
}

目标是将 StateItem 列表存储在 MenuState 列中作为Json数组。如果只将 StateItem 存储在表中,它可以正常工作。但一旦我将它们定义为Owned类,我会遇到这个错误:

System.ArgumentException: 表达式类型为 'System.Object' 不能用于赋值到类型 'System.Int32'

我认为问题与主键定义有关。但如果我尝试定义主键,EF会坚持认为主键需要隐式定义。

所以,使用EF Core的Json支持存储Json数组是否可能?

英文:

Is it possible to store a Json list in a DB column leveraging EF Core 7 Json support? I tried without success.

I have these classes (simplified):

public class StateData
{
    public int Id { get; set; }
    public int DemandId { get; set; }
    public List&lt;SateItem&gt;? MenuState { get; set; }
    public int? LastMenuItem { get; set; }
}

public class StateItem
{
    public int SideMenuItemId { get; set; }
    public int StateDataId { get; set; }
    public int Order { get; set; }
    public string Header { get; set; } = null!;
    }
}

And this DbContext:

public ApplicationDbContext(DbContextOptions&lt;ApplicationDbContext&gt; options)
    : base(options)
{
}

public DbSet&lt;StateData&gt; StateData { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new StateDataConfiguration());
}

With configuration:

public class StateDataConfiguration : IEntityTypeConfiguration&lt;StateData&gt;
{
    public void Configure(EntityTypeBuilder&lt;StateData&gt; builder)
    {
        builder.OwnsMany(d =&gt; d.MenuState, builder =&gt;
        {
            builder.ToJson();
        });
    }
}

The goal is to store the list of StateItem's in the MenuState column as a Json array. If I just store StateItem's in a table, it works. As soon as I make them an owned class, I get this error:

> System.ArgumentException: Expression of type 'System.Object' cannot be used for assignment to type 'System.Int32'

I think, the problem has to do with primary key definition. But if I try to define primary keys, EF insists that keys need to be implicitly defined.

So, is it even possible to store Json array with EF Core's Json support?

答案1

得分: 1

我遇到了相同的问题,我的JSON类中有一个ID列。也许EF Core正试图自动插入某些内容?当我删除它时,它起作用了。有可能它将你的"SideMenuItemId"和"StateDataId"列解释为ID列吗?如果你将它们重命名为StateDataIdentifier或其他名称会怎样?

英文:

I had the same issue, where my JSON class had an ID column. Maybe EF Core is trying to autoinsert something in to this? Worked when I removed it. Is it possible that it's interpreting your "SideMenuItemId" and "StateDataId" columns as ID columns? What if you rename them to StateDataIdentifier or something?

答案2

得分: 0

Maybe, using JsonProperty.EFCore can solve your problem. You can install it as a nuget package.

In your case:

using JsonProperty.EFCore;

public class StateData
{
    public int Id { get; set; }
    public int DemandId { get; set; }
    public JsonList&lt;SateItem&gt; MenuState { get; set; } = new();
    public int? LastMenuItem { get; set; }
}

Other usage example:

using JsonProperty.EFCore;

//Create product
var product = new Product() { Name = &quot;Car&quot; };

//AddRange
product.Attributes.AddRange(new Dictionary&lt;string, object&gt;() {
    //You can add values ​​of different types if the base type is object 
    {&quot;MaxSpeed&quot;,300},{ &quot;Engine capacity&quot;,3.5}, { &quot;ElectroCar&quot;,false }
});

//Add
product.Attributes.Add(&quot;Color&quot;, &quot;Red&quot;);

//Edit
product.Attributes.Edit(attrs=&gt;{
    attrs[&quot;Color&quot] = &quot;Blue&quot;;
    return attrs;
});

//Entity model
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    //Json container property. Same type as JsonDictionary&lt;string,object&gt;
    public JsonDictionary Attributes{ get; set; } = new();
}
英文:

Maybe, using JsonProperty.EFCore can solve your problem. You can install it as a nuget package.

In your case:

using JsonProperty.EFCore;

public class StateData
{
    public int Id { get; set; }
    public int DemandId { get; set; }
    public JsonList&lt;SateItem&gt; MenuState { get; set; } = new();
    public int? LastMenuItem { get; set; }
}

Other usage example:

using JsonProperty.EFCore;

//Create product
var product = new Product() { Name = &quot;Car&quot; };

//AddRange
product.Attributes.AddRange(new Dictionary&lt;string, object&gt;() {
    //You can add values ​​of different types if the base type is object 
    {&quot;MaxSpeed&quot;,300},{ &quot;Engine capacity&quot;,3.5}, { &quot;ElectroCar&quot;,false }
});

//Add
product.Attributes.Add(&quot;Color&quot;, &quot;Red&quot;);

//Edit
product.Attributes.Edit(attrs=&gt;{
    attrs[&quot;Color&quot;] = &quot;Blue&quot;;
    return attrs;
});

//Entity model
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    //Json container property. Same type as JsonDictionary&lt;string,object&gt;
    public JsonDictionary Attributes{ get; set; } = new();
}

huangapple
  • 本文由 发表于 2023年3月1日 16:22:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75601122.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定