实体框架将多个属性序列化到一列
本文关键字:一列 序列化 框架 属性 实体 | 更新日期: 2023-09-27 18:17:32
我想把下面的类映射到一个表,使用实体框架,最好有流畅的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和名称列,以及在"SerializedData"列中序列化的所有其他属性?
如果不是"only"其他属性,整个对象也可以在SerializedData列中序列化
谢谢,史蒂文
另一个类似Drew的答案是:
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上。 虽然这个问题是问实体框架,我有完全相同的问题,但实体框架核心。事实证明,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;}
}
然后配置您的模型以忽略您不想映射到单个列的属性,并添加shadow属性:
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字符串并设置"Data"阴影属性,像这样:
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,通过利用他们的新的阴影属性特性。