使用通用域模型的 DAL 架构

Posted

技术标签:

【中文标题】使用通用域模型的 DAL 架构【英文标题】:DAL architecture using generic domain models 【发布时间】:2012-06-09 13:02:21 【问题描述】:

目前我面临的问题是,我尝试为我的 .NET 应用程序设计一个 DAL,该应用程序稍后将使用某种 NoSQL 数据库。 我现在评估的 NoSQL 数据库有时在用作主键的类型上有所不同。例如,MongoDB 使用专有的ObjectID,而 RavenDB 使用通用的string。 所以我的问题是,我如何设计这样一个可以处理不同类型的域模型 id 的 DAL。

我的第一个方法是制作通用领域模型。 这看起来像这样:

// Domain Model
public class Filter<TId> 
  public TId Id  get; set; 
  // ...


// DAO-interface
public interface IFilterDao<TId> 
  bool Persist(Filter<TId>);
  // ...


// This is where the problems begin
public static class DAOFactory 
  public static IFilterDAO<T> GetFilterDAO<T>() 
    // Implementation of IFilterDAO<T> can't be instantiated because types must be known at compile time
  

DAO-Factory方法中的注释已经描述了问题:我不能在运行时定义T,因为对应的代码是在编译时生成的。

我的第二种和第三种方法是将Id 定义为objectdynamic。 RavenDB 无法使用object,因为它需要一个字符串。使用 dynamic 我无法将 lambdas 传递给 RavenDB API(发生编译器错误“表达式树可能不包含动态操作”)。 构建表达式树而不是使用 lambda 确实是最后的出路,因为它更耗时。

所以我完全陷入困境,我希望有人可以帮助我。 提前致谢。

更新:我终于让 RavenDB 与 object 一起工作,但使用 object 并不是一个令人满意的解决方案。

【问题讨论】:

【参考方案1】:

如果您在编译时知道类型,您可以在静态类中解决问题,对吗?这意味着,您必然需要为每个底层数据库实现一个 DaoFactory。

答案是您不应该使用factory pattern - 相反,您应该使用abstract factory pattern。

public class Filter<TId>  
  public TId Id  get; set;  
 

public interface IFilterDao<TId>  
  bool Persist(Filter<TId>); 
 

// Note: Can't be static since polymorphism requires an instance!
public abstract class DaoFactory<TId> 
  public abstract IFilterDao<TId> GetFilterDao<TId>();


public sealed class MongoDBDaoFactory : DaoFactory<ObjectID> 
  public override IFilterDao<ObjectID> GetFilterDao<ObjectID>()  /* ... */ 


public sealed class RavenDBDaoFactory : DaoFactory<String> 
  public override IFilterDao<String> GetFilterDao<String>()  /* ... */ 

我不得不做类似的事情并尝试使用dependency injection pattern 来选择在运行时使用的适当实现,但由于泛型问题,这实际上很难做到。 抽象工厂是最好的去处。

【讨论】:

但现在我必须明确告诉编译器我想要一个例如MongoDBFactory,不是吗?我的意思是,如果我创建工厂,我仍然必须提供这样的类型:DaoFactory&lt;ObjectId&gt; factory = new MongoDBFactory(); 这正是我想要放入配置中的内容。 真;就像我说的,使用 DI 对于通用接口变得非常棘手。我知道可以做到(例如,我相信微软的 Unity 就是这样做的);我只是不确定这是你真正想要做的。毕竟,无论如何,您必须知道客户端代码中的 TId 类型,对吧?很有可能,如果您要在完全不同的数据库之间迁移,那么重新编译代码将是您最不关心的问题。 我想你是对的,我会在更高层面临更多问题。如果 DI 真的那么棘手,我想这不是一个选择。我不想在完全不同的数据库之间迁移,而只是在相似的数据库之间迁移(例如,只有文档存储)。我将使用 DI 检查解决方案,如果不满意,我可能会将 id 的类型统一为object。谢谢你的帮助。 +1 提供的答案。 不客气。如果您找到更好的方法,请告诉我!

以上是关于使用通用域模型的 DAL 架构的主要内容,如果未能解决你的问题,请参考以下文章

WCF 作为业务逻辑

业务层 (BLL) 数据访问层 (DAL) 和 UI 之间的通用结构?

谈谈通用对账平台的业务架构设计

快速架构通用AI模型生产体系,商汤科技是怎么做到的?

[架构之路-11]:目标系统 - 架构 - 嵌入式系统软件+硬件的基本通用架构

推荐系统[七]:推荐系统通用技术架构(Netfilx等)API服务接口