我可以在EF实体中嵌入一个对象(在保存时序列化,在访问时反序列化)?

时间:2013-02-08 19:14:09

标签: entity-framework ef-code-first

我有一个类,我想保留元数据 - 有几个交互场景,所以meta允许我为不同的交互类型保留不同的元数据。

class Feed()
{
    Guid FeedId { get; set; }
    ObjectMetaDictionary Meta { get; set; }
}

我希望EF能够序列化这个ObjectMetaDictionary并将其作为字符串/ VarChar存储在数据库中。当我检索一条记录时,我希望它被反序列化为ObjectMetaDictionary。

EF是否支持此功能?我该怎么办?

我正在使用Entity Framework Code First。

已解决:我在下方提供了一个解决了我的问题的答案。一旦SO允许我,我会接受这个答案。

3 个答案:

答案 0 :(得分:23)

显然这实际上非常简单。由于之前的SO answer提供了一些帮助,我能够让它工作。

OnModelCreating中的Fluent配置允许我们告诉EF使用什么作为序列化到DB的值属性并再次退出。

这是我的解决方案:

public class Feed
{
    public virtual Guid FeedId { get; set; }

    public virtual FeedMetaData Meta { get; set; }

    public virtual string Title { get; set; }
    public virtual string Description { get; set; }

}

public class FeedMetaData
{
    public Dictionary<string, string> Data { get; set; }

    public string Serialized
    {
        get { return JsonConvert.SerializeObject(Data); }
        set
        {
            if(string.IsNullOrEmpty(value)) return;

            var metaData = JsonConvert.DeserializeObject<Dictionary<string, string>>(value);

            Data = metaData ?? new Dictionary<string, string>();
        }
    }

    // addl code removed...
}

public class FeedsDbContext : DbContext
{
    public DbSet<Feed> Feeds { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.ComplexType<FeedMetaData>()
                    .Property(p => p.Serialized)
                    .HasColumnName("Meta");
        modelBuilder.ComplexType<FeedMetaData>().Ignore(p => p.Data);

        base.OnModelCreating(modelBuilder);
    }
}

答案 1 :(得分:1)

让您的Entity Framework对象简单,并为数据库中的列提供String属性。

class Feed()
{
    Guid FeedId { get; set; }
    String Meta { get; set; }
}

创建保存和加载属性的方法:(因为我已经使用了EF,所以我已经有一段时间了,所以我不确定你是否可以用这些getter创建一个瞬态属性/ setters或者如果你需要别的东西)

//Reading from string column Meta
(ObjectMetaDictionary) XamlServices.Load(new StringReader(someFeed.Meta));

//Saving to string column Meta
someFeed.Meta = XamlServices.Save(value);

这给你的项目带来了另一个问题。更改ObjectMetaDictionary可能会导致它无法正确地从数据库反序列化。您的ObjectMetaDictionary基本上成为数据库架构的一部分,您需要相应地处理版本控制或更改。

答案 2 :(得分:0)

HasConversion功能挽救了我的生命。解锁所有json格式!享受吧!

public partial class Feed
{
    public int Id { get; set; }

    //this column will be mapped to a "nvarchar(max)" column. perfect!
    public Dictionary<string, string> Meta { get; set; }
}

public class FeedsDbContext : DbContext
{

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

    public virtual DbSet<Feed> Feed { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<Feed>(entity =>
        {
            entity.Property(p => p.Meta).HasConversion(
                x => JsonConvert.SerializeObject(x) //convert TO a json string
                , x => JsonConvert.DeserializeObject<Dictionary<string, string>>(x) //convert FROM a json string
            );
        });
    }

}