数据库对象持久化设计探讨

在软件开发中,对象的持久化是一个常见而重要的议题。透明激活(transparent activation)作为一种延迟加载技术,能够显著提高应用程序的性能。本文将探讨如何在不违反领域模型独立性的前提下,实现透明激活。

透明激活的挑战

透明激活要求存储的对象具备某些功能,但这与领域模型不应依赖于其持久化方式的设计理念相冲突。为了解决这一矛盾,需要在设计上做出一些权衡和创新。

代码实现

代码实现的关键在于设计而非编码本身。作者首先考虑了NHibernate的经验,其中每个领域类都类似于以下形式:

public class Book { public virtual string Name { get; set; } }

NHibernate会自动创建一个Book类的派生类,包含所有必要的修改。然而,db4o不会为做这些,所以需要自己实现IActivatable接口。

实现透明激活的选项

有几种实现透明激活的选项:

  • 编写代码生成
  • 为每个数据访问层(DAL)类创建派生类
  • 在领域中创建一个通用基类并实现所需更改

选项1非常复杂,通常被认为是一种负担,除非db4o的开发者。选项2看起来合理,但C#不支持多重继承,将不得不一遍又一遍地复制粘贴大量代码。

创建派生类的示例

以下是派生类的一个示例:

public class DALBook : Domain.Book, IActivatable { public virtual string Name { get { Activate(ActivationPurpose.Read); return base.Name; } set { Activate(ActivationPurpose.Write); base.Name = value; } } [Transient] private IActivator _activator; public void Activate(ActivationPurpose purpose) { if (_activator != null) { _activator.Activate(purpose); } } public void Bind(IActivator activator) { if (_activator == activator) { return; } if (activator != null && null != _activator) { throw new System.InvalidOperationException(); } _activator = activator; } }

为了实现透明激活,每个DAL类都需要这样的部分。

创建通用基类

为了使代码更加灵活,可以考虑创建一个通用的超类来实现Activate和Bind方法。

public interface Book { string Name { get; set; } }

在数据访问层(DAL),可以创建一个适当的继承层次结构,其中基类实现了每个可持久化对象真正通用的逻辑。

internal abstract class Db4oBase : IActivatable { [Transient] private IActivator _activator; public void Activate(ActivationPurpose purpose) { if (_activator != null) { _activator.Activate(purpose); } } public void Bind(IActivator activator) { if (_activator == activator) { return; } if (activator != null && null != _activator) { throw new System.InvalidOperationException(); } _activator = activator; } } internal class DALBook : Db4oBase, Domain.IBook { private string name_; public virtual string Name { get { Activate(ActivationPurpose.Read); return name_; } set { Activate(ActivationPurpose.Write); name_ = value; } } }

所有DAL类都标记为internal,因为DAL客户端应该只知道领域接口。因此,需要实现一个基于所需接口创建具体类的解决方案。例如:

public static class DAOFactory { public static T CreateDomainObject() { string dalClass = string.Format("DAL.{0}", typeof(T).Name.Substring(1)); return (T)Type.GetType(dalClass).GetConstructor(Type.EmptyTypes).Invoke(null); } } Domain.IBook book = DAL.DAOFactory.CreateDomainObject();
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485