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 可以是 Dictionary 或任何其他复杂类型。

4

2 回答 2

8

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

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

另一种方法是使用 EF 的挂钩来实现和保存更改。您将需要处理ObjectContext.ObjectMaterialized事件(您可以ObjectContext通过DbContextIObjectContextAdapter显式实现DbContext)。在此事件处理程序中,您将使用字符串属性的值并将其内容反序列化为MyClass属性。您还必须覆盖DbContext.SaveChanges在哪里查找Message应该插入或更新的所有实例,并使用它们的MyClass属性来获取当前值并将其序列化为字符串属性。

您正在寻找的是一些复杂的映射场景或映射转换。EF 不支持它们,但您可以投票支持我对Data UserVoice的建议。

于 2012-07-03T08:23:28.453 回答
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);
    }
}
于 2019-03-25T14:13:38.340 回答