2016-02-12 80 views
1

我正在使用最新版本的NHibernate,最近我偶然发现了一个有趣的问题。在某些情况下ORM额外的计算列?

比方说,我有一个名为Profile的表,我想要接收我的所有配置文件的列表。但是,有了它,我有一个名为CanDelete的计算列,它禁止在(例如)正在使用的情况下删除配置文件。

但是,这CanDelete计算列不是我的实体的一部分,我不想污染实体,当我在这种情况下只需要CanDelete值 - 并且对每个配置文件单独计算它太慢。

有没有在NHibernate的方式执行某些查询并获取该查询的行作为对象,但然后以某种方式获取一个额外的计算列以及?

假设我正在使用N层体系结构。在表示层中,我需要一个所有配置文件的列表(并且对于每个配置文件,我是否可以删除它)。我的业务逻辑层和数据访问层如何看起来像?

现在在我的资源库中,我有一个GetProfiles方法,然后我运行了一个CanDeleteProfile方法,用于获取每个配置文件。但就像我上面提到的那样,它太慢了。我可以创建一个GetProfilesWithCanDeleteStatus方法,但这需要我创建一个专门的实体,并在其上包含该计算列。

当我不想在配置文件列表中击中O(n^2)性能时,如何以适当方式构建此建议,您有什么建议?我想避免n + 1问题。

我不一定在寻找一个NHibernate解决方案(我标记了NHibernate,因为它可能有这种类型的东西的一些特定的工具),并欢迎其他ORM的一般解决方案。

回答

0

我有一个想法可能对你有好处,但它不会是一个完美的想法,因为你设计你的程序的方式都有缺点。

我建议你更改该列的定义CanDelete,这样它就像该实体中的任何其他列(不在运行时计算)和布尔类型,但不会破坏需求。

通过这样做,它会像db中的任何其他简单的Select - 这非常快。

现在,棘手的部分是确保该列将指示(在任何时候需要)它是否已被使用(以及是否可以删除)。

因为如果使用Profile实体(并且可以删除),我不知道计算的方式,但很难说清楚如何精确设计DAL和BL,但指导原则是: 在其他每个地方更改DB(该实体或其他实体)中的一个状态,该状态可能会改变您使用函数封装的列CanDelete以再次计算该值以验证其状态并在需要时更改它。

如果您确保每次在BL中更改其中一列CanDelete的计算方式,那么您确保CanDelete列始终为真。

这种方法的缺点是: 1。它会在程序员需要时不使用封装函数的时候出错。 2.它假设这个应用程序是唯一一个改变这个数据库。 3.从管理工作室或脚本插入原始数据时必须小心。

我希望它对你的BL好。