c# - 我可以在 NHibernate 中使用实体代理接口(interface)的基类型安全地查询吗?

标签 c# nhibernate

我目前正处于多个相当复杂的系统的设计阶段,这些系统具有共同的功能(例如,两者都具有客户关系管理 (CRM) 和销售功能)。因此,我试图提取域的公共(public)部分并在两个应用程序中重用它。

假设我有应用程序 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): Application design

为了持久化,我使用 NHibernate。 A 和 B 都提供自己的映射(按代码映射)以包含额外的属性。另外,A定义IACustomer为ACustomer的代理类型,B定义IBCustomer为BCustomer的代理类型。

我现在可以使用 NHibernate 来处理 A 和 B 中的实体,例如在一个

session.QueryOver<ACustomer>()
    .Where(c=>c.ReceivesNewsletter)
    .List()

现在假设我想在基础库中对客户做一些事情(例如在某种服务对象中)。我刚刚制作了一个非常简单的版本的原型(prototype),到目前为止这似乎工作正常:

session.QueryOver<ICustomer>()
   .Where(c => c.CustomerNumber == "1234ABC")
   .List()

也就是说,我可以在 QueryOver 中使用特定实体的代理类型的基类,而 NHibernate 会创建正确的查询,例如在答:

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)] 

我的问题

这些查询是否总是按预期工作?我能否始终在基础库的查询中安全地使用代理接口(interface)的基础类型? NHibernate 是否总能找到“正确”的实体类型和要检索的表?或者是否会出现这对查询效率产生不利影响的情况 b/c NHibernate 需要做猜测工作?在这种情况下我应该注意的任何其他陷阱?

我在文档中找不到相关信息。这种方法可以让我巧妙地将某些域的公共(public)部分移动到它们自己的基础库中,但我想确保它有效。

最佳答案

我看不出这种情况有什么问题。 特别是因为在每个应用程序中只有一个 ICustomer 实现。

即使每个应用程序都有多个实现,您也可能会遇到按 id 加载的问题 (session.Load(42),因为可能有多个客户具有该 id,具体取决于您的映射).但接收客户列表的查询仍然有效。

当我过去使用 NHibernate 研究与您的问题类似的问题时,我阅读了这篇文章 - 它讨论的是派生基类而不是接口(interface),但它的想法是一样的:http://codebetter.com/jameskovacs/2011/02/16/getload-polymorphism-in-nhibernate-3/

NHibernate 不会猜测 - 在初始化时,它会为任何给定类型构建所有映射的存储,当您为任何类型编写查询时,它会找到它已映射并继承自它的正确类型并进行相应的查询。

关于c# - 我可以在 NHibernate 中使用实体代理接口(interface)的基类型安全地查询吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14362374/

相关文章:

c# - .NET 4.6 中的 NHibernate 按代码映射抛出 "Cannot extend unmapped class"

nhibernate - Fluent NHibernate - 将引用键列设置为空

c# - 如何在 WPF 中将变量作为 ConverterParameter 传递

c# - WebView 即使应用程序处于后台/关闭时也如何运行(前台服务处于事件状态)

c# - 作为当前用户使用 Web 服务添加列表项

c# - 我怎样才能得到二叉树中的 parent

c# - 如果实体处于某种状态,如何强制执行约束,例如任何字段(或特定字段)不得更改?

c# - NHibernate QueryOver 两次加入一个集合

c# - 从 HTML <figure> 和 <figcaption> 到 Microsoft Word

NHibernate Criteria.AddOrder(Order.Asc ("Column.Property"))