我想说,解决方案应该分成两部分。 1)序列化的东西的映射和2)序列化。我正在使用 NHibernate。 这种情况实际上与存储 1)文件路径 2)在共享上查找文件的更常见问题非常相似。
映射。这是微不足道的。只需介绍新的属性ExtraInfo,可以在基础级别
public virtual string ExtranInfo { get; set; }
不管使用什么 ORM 工具,我们都会简单地将其映射到一个 nvarchar 列 ExtraInfo。
继承也很简单,对于NHibernate我们可以使用8.1.1. Table per class hierarchy(我忍不住,xml映射更具可读性,但fluent也会这样做)
<class name="Base" table="BaseTable">
<!-- common id -->
<id name="Id" generator="native" />
<!-- the column keeping the subtype selector -->
<discriminator column="Type" type="String"/>
<!-- base properties
<property name="Name" />
<property name="ExtraInfo" /> <!-- the JSON -->
<subclass name="Alpha" discriminator-value="Alpha" />
<subclass name="Beta" discriminator-value="Beta" />
<!-- ... more subclasses -->
</class>
序列化。它取决于架构(部分取决于 ORM 工具)。我们可以使用与读写操作挂钩的 AOP(首选解决方案)来创建 JSON 或填充其他属性。 NHibernate 支持12.1. Interceptors 和12.2. Event system
Hibernate/NHibernate世界中的Intercepting综合讲解could be found here
查询如何获取我们的Alpha:
ISession session = ... // get NHSession standard way
var result = session.Query<Base>()
.Where(b => b is Alpha)
.Take(1)
.Cast<EmployeeField>()
.ToList<EmployeeField>()
所以在这种情况下,OnLoad 方法中的 Interceptor 可以访问所有加载的信息,并且可以为我们完成这项工作
public override bool OnLoad(object entity, object id,
object[] state, string[] propertyNames, IType[] types)
NHibernate 还有另一个不错的功能:IResultTransformer。它可以通过这种方式注入到查询处理中(16. QueryOver Queries):
// not linq but QueryOver
var result = session.QueryOver<Base>()
.Where(b => b is Alpha)
// here we go
.TransformUsing(new MyTransformer())
.Take(1)
.List<Alpha>()
自定义ResultTransformer implementation的示例,基本方法的签名:
public object TransformTuple(object[] tuple, string[] aliases)
{
总结。尽管事实上,将属性存储为 JSON 并不是开箱即用的支持,但我们可以通过简单的 varchar 列持久性和一些 AOP/拦截器来管理它。
阅读“动态列/属性”如何在 NHibernate 中工作可能会很有趣:NHibernate Dynamic Columns Number