Entity Framework:序列化/反序列化幕后的JSON列

8

我有一个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可以是字典或任何其他复杂类型。


这可能会有所帮助:http://www.reddnet.net/entity-framework-json-column/ - CAD bloke
2个回答

8
不是直接的。你必须始终在类中拥有你的字符串属性,因为EF需要它来进行持久化。你还可以拥有未映射的MyClass属性,但你必须手动处理序列化和反序列化,并使这些属性保持同步。
天真的解决方案是在你的MyClass中实现INotifyPropertyChanged,确保每次更改MyClass值或其任何属性都会触发JSON序列化到字符串属性。这种天真的解决方案对于一些简单的问题有效,但在这种情况下,这是一个非常糟糕的想法,因为如果你修改了分配的MyClass属性的许多属性,它会产生很大的性能影响。
另一种方法是使用EF的钩子进行物化和保存更改。你需要处理ObjectContext.ObjectMaterialized事件(可以通过DbContextIObjectContextAdapter显式实现获取ObjectContext)。在这个事件处理程序中,你将使用字符串属性的值,并将其内容反序列化为MyClass属性。你还需要重写DbContext.SaveChanges,在其中查找所有应该插入或更新的Message实例,并使用它们的MyClass属性来获取当前值并将其序列化为字符串属性。
你要寻找的是一些复杂的映射场景或映射转换。EF不支持它们,但你可以在Data UserVoice上投票支持我的建议。

你可以尝试使用属性的getter方法进行序列化,setter方法进行反序列化并填充对象的其余部分,而不是使用Entity的钩子。 - Kevin Kibler
@KevinKibler 这个方案与INotifyPropertyChanged解决方案存在相同的问题,但它可以工作。 - Casey

2
我会尝试以下方法:

我会尝试以下方法:


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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接