实体框架:在场景后面序列化/反序列化JSON列

时间:2012-07-02 23:05:05

标签: c# json entity-framework-4

我有Code First类/表,其中一个字段的类型为string / nvarchar。此字符串是MyClass实例的JSON表示形式。我想在仅使用MyClass实例的代码中操作,但是将其作为字符串(JSON)存储在数据库中。假设我的表看起来像这样:

public class Message
{
    [Key]
    public int Id { get; set; }
    public string Title { get; set; }
    public string JsonDefinition { get; set; }
}

我更喜欢这样的

public class Message
{
    [Key]
    public int Id { get; set; }
    public string Title { get; set; }
    [JSON]
    public MyClass JsonDefinition { get; set; }
}

其中JSON是一个自定义属性,它告诉EF将字段存储为MyClass实例的序列化字符串。同时它说EF:“一旦你拉动实体,用反序列化的MyClass实例替换JsonDefinition字符串”

是否可以使用现有的EF 4机制实现?如果是这样,那怎么样?

提前致谢。

编辑:MyClass可以是字典或任何其他复杂类型。

2 个答案:

答案 0 :(得分:8)

不直接。您必须始终在类中包含字符串属性,因为EF要求它具有持久性。您还可以拥有非映射MyClass属性,但必须手动处理序列化和反序列化,并使这些属性保持同步。

天真的解决方案是在MyClass中实现INotifyPropertyChanged并确保MyClass值或其任何属性中的每个更改都会触发到字符串属性的JSON序列化。这种天真的解决方案适用于一些简单的问题,但在这种情况下,这是一个非常糟糕的主意,因为如果您在指定的MyClass属性上修改了很多属性,它会对性能产生很大的影响。

另一种方法是使用EF的钩子进行物化并保存更改。您需要处理ObjectContext.ObjectMaterialized事件(您可以ObjectContext通过DbContext明确实施的IObjectContextAdapter获取DbContext。在此事件处理程序中,您将使用字符串属性的值并将其内容反序列化为MyClass属性。您还必须覆盖DbContext.SaveChanges,您将在其中查找应插入或更新的所有Message实例,并使用其MyClass属性获取当前值并将其序列化为字符串属性。< / p>

您正在寻找的是一些复杂的映射方案或映射转换。 EF不支持他们,但您可以在Data UserVoice上投票赞成我的建议。

答案 1 :(得分:0)

我会尝试以下操作:

public class Message
{
    [Key]
    public int Id { get; set; }
    public string Title { get; set; }

    [Column(TypeName = "jsonb")]
    [JsonIgnore]
    public string JMyClass { get; set; }

    [NotMapped]
    public MyClass JsonDefinition 
    {
        get => JsonConvert.DeserializeObject<MyClass>(JMyClass );
        set => JMyClass = JsonConvert.SerializeObject(value);
    }
}