簡體   English   中英

實體框架將多個屬性序列化為一列

[英]Entity framework serialization multiple properties to one column

我想將以下類映射到表,使用實體框架,最好使用流暢的 api。

public class MyEntity
{
    public int Id {get;set;}
    public string Name {get;set;}
    public int Age {get;set;}
    public string OtherData {get;set;}
    public List<Blabla> BlaBlaList {get;set;}
}

表 MyEntity:

column Id
column Name
column SerializedData

是否可以僅將 Id 和 Name 映射到列,以及在“SerializedData”列中序列化的所有其他屬性?

如果不是“僅”其他屬性,則整個對象也可能在 SerializedData 列中被序列化

謝謝,史蒂文

類似於德魯的答案的另一個答案是執行以下操作:

public class MyEntity : IMySerializable
{
  public int Id {get;set;}
  public string Name {get;set;}

  [NotMapped]
  public int Age {get;set;}
  [NotMapped]
  public string OtherData {get;set;}
  [NotMapped]
  public List<Blabla> BlaBlaList {get;set;}

  public byte[] SerializedData  
  {
    get
    {
      return this.MySerialize();
    } 
    set 
    {
      this.MyDeserialize(value);
    }
  }
}

然后是一種擴展方法,允許您對多個實體執行此操作:

public static IMySerializableExtensions
{
  public static byte[] MySerialize<T>(this T instance)
    where T : IMySerializable
  {
    byte[] result = // ...

    // code

    return result;
  }

  public static void MyDeserialize<T>(this T instance, byte[] value)
    where T : IMySerializable
  {
     // deserialize value and update values
  }
}

您可以確定要反序列化/序列化的屬性,因為它們將具有NotMappedAttribute

你必須自己做...

我建議為您的數據庫映射創建一個單獨的類,並將“MyEntity”作為 POCO。 這最終取決於偏好,但我更喜歡讓我的實體盡可能接近數據庫結構。 以這種方式維護更容易。

因此,話雖如此,創建一個單獨的類,它是您將實際與之交互的對象,並為其提供一個實例方法來序列化自身,以及一個用於反序列化的靜態方法。 我在這里使用了 JSON,但你可以為所欲為。 注意我還添加了一個方法來將其轉換為 MyDBEntity:您的邏輯可能會在其他地方,但這應該讓您了解如何去做。

public class MyEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string OtherData { get; set; }
    public List<int> BlaBlaList { get; set; }

    public byte[] Serialize()
    {
        string json = JsonConvert.SerializeObject(this);
        return Encoding.ASCII.GetBytes(json);
    }

    public static string Deserialize(byte[] objectBytes)
    {
        return Encoding.ASCII.GetString(objectBytes);
    }

    public MyDBEntity ConvertToDBEntity()
    {
        MyDBEntity dbEntity = new MyDBEntity();
        dbEntity.ID = Id;
        dbEntity.Name = Name;
        dbEntity.SerializedData = this.Serialize();
        return dbEntity;
    }
}

public class MyDBEntity
{
    public int ID { get; set; }
    public string Name { get; set; }
    public byte[] SerializedData { get; set; }
}

接下來,將 MyDBEntity 類添加到您的上下文中:

public class EFContext : DbContext
{
    public DbSet<MyDBEntity> Entities { get; set; }
}

就是這樣! 現在你可以做類似的事情

 using (var db = new EFContext())
    {
        MyEntity me = new MyEntity();
        me.Name = "Bob";
        me.Age = 25;
        me.OtherData = "he does stuff";
        me.BlaBlaList = new List<int> { 7, 8, 9 };
        MyDBEntity newEntity = me.ConvertToDBEntity();

        db.Entities.Add(newEntity);
        db.SaveChanges();
    }

我為這個答案設計了一個小控制台應用程序,如果你願意,我把它放在Github 上

雖然這個問題是針對 Entity Framework 提出的,但我有完全相同的問題,但針對 Entity Framework Core。 事實證明,EF Core 有一種更優雅的方法來將序列化數據存儲在單個列中,同時允許單個屬性存在於域模式中。 更優雅,因為它不需要對域模型本身進行任何更改。

它是這樣的:

您的實體保持原樣:

public class MyEntity
{
    public int Id {get;set;}
    public string Name {get;set;}
    public int Age {get;set;}
    public string OtherData {get;set;}
    public List<Blabla> BlaBlaList {get;set;}
}

然后配置您的模型以忽略您不想映射到單個列的屬性,並添加一個陰影屬性:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Ignore(x => x.Age);
    modelBuilder.Ignore(x => x.OtherData);
    modelBuilder.Ignore(x => x.BlaBlaList);

    // Adding a "shadow" property called "Data".
    modelBuilder.Property<string>("Data");
}

現在保存實體時,您可以簡單地將所需的屬性序列化為 JSON 字符串並設置“數據”陰影屬性,如下所示:

var entity = new MyEntity { ... };

var data = new
{
   entity.Age,
   entity.OtherData,
   entity.BlaBlaList
};

var json = JsonConvert.Serialize(data);

_dbContext.Property("Data").CurrentValue = json;

從存儲加載實體時,請確保重新水合屬性:

var entity = await _dbContext.MyEntities.FirstOrDefaultAsync(...);

// Simply re-constructing the anonymous type for deserialization. It's not necessary to actually initialize each field with the current values (which are empty anyway), but this is just a convenient way to model the anonymous type.

var data = new
{
   entity.Age,
   entity.OtherData,
   entity.BlaBlaList
};

var json = _dbContext.Property("Data").CurrentValue = json;
data = JsonConvert.DeserializeAnonymousType(json, data);

entity.Age = data.Age;
entity.OtherData = data.OtherData;
entity.BlaBlaList = data.BlaBlaList;

就是這樣。 EF Core 允許您通過利用域模型的新陰影屬性功能將域模型用作純粹、干凈的 POCO。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM