我目前处于多个相当复杂的系统的设计阶段,这些系统共享共同的功能(例如,两者都有客户关系管理(CRM)和销售功能)。因此,我试图提取域的公共部分并在两个应用程序中重用它。
假设我有应用程序 A 和应用程序 B,它们都使用 CRM 功能。在大多数情况下,CRM 功能是相同的,但两个应用程序都喜欢增加一些与 CRM 相关的东西。
我想创建一个实现 CRM 系统基本版本的库,例如将客户抽象为
interface ICustomer {
string CustomerNumber {get;set;}
}
基础库有 ICustomer 的基本实现
class Customer: ICustomer
应用程序 A 现在可以增强它:
interface IACustomer : ICustomer {
bool ReceivesNewsletter {get;set;}
}
class ACustomer : Customer, IACustomer {
...
}
同样,B 也有自己的变体:
interface IBCustomer : ICustomer {
string NickName {get;set;}
}
class BCustomer : Customer, IBCustomer {
....
}
出于抽象的目的,我从不在基础库中实例化具体类型,而是使用工厂或 DI 容器,例如:
interface ICrmFactory {
ICustomer CreateCustomer();
}
A 和 B 相应地实现工厂,以便分别创建 ACustomers 或 BCustomers。
这是我的意思的UML图(未显示应用程序B):
对于持久性,我使用 NHibernate。A 和 B 都提供自己的映射(按代码映射)以包含额外的属性。另外,A 定义 IACustomer 为 ACustomer 的代理类型,B 定义 IBCustomer 为 BCustomer 的代理类型。
我现在可以使用 NHibernate 来处理 A 和 B 中的实体,例如 A
session.QueryOver<ACustomer>()
.Where(c=>c.ReceivesNewsletter)
.List()
现在假设我想对基础库中的客户做一些事情(例如在某种服务对象中)。我刚刚制作了一个非常简单的版本的原型,到目前为止这似乎工作正常:
session.QueryOver<ICustomer>()
.Where(c => c.CustomerNumber == "1234ABC")
.List()
也就是说,我可以在QueryOver中使用特定实体的代理类型的基类,NHibernate会创建正确的查询,例如在A中:
SELECT
this_.Id as Id0_0_,
this_.CustomerNumber as Customer2_0_0_,
this_.ReceivesNewsletter as Receives3_0_0_
FROM
ACustomer this_
WHERE
this_.CustomerNumber = @p0;
@p0 = '1234ABC' [Type: String (4000)]
我的问题
这些查询会始终按预期工作吗?我可以在基本库的查询中始终安全地使用代理接口的基本类型吗?NHibernate 是否总能找到“正确”的实体类型和要检索的表?或者是否会在某些情况下对查询效率产生不利影响 b/c NHibernate 需要进行猜测工作?在这种情况下我应该注意的任何其他陷阱?
我在文档中找不到有关此的信息。这种方法可以让我巧妙地将某些域的公共部分移动到他们自己的基础库中,但我想确保它有效。