使用Fluent NHibernate映射由两列之一连接的集合?
我正在建立会计模型,其中我的账户有借记一个账户,贷记另一个账户的交易 以下是详细情况(简化)。我的表(在SQL Server 2008中)是: 我的课程是: where子句中的重要部分是或 所以我需要的代码是:使用Fluent NHibernate映射由两列之一连接的集合?,nhibernate,fluent-nhibernate,Nhibernate,Fluent Nhibernate,我正在建立会计模型,其中我的账户有借记一个账户,贷记另一个账户的交易 以下是详细情况(简化)。我的表(在SQL Server 2008中)是: 我的课程是: where子句中的重要部分是或 所以我需要的代码是: 公共类AccountMap:子类映射 { 公共帐户映射() { Id(x=>x.Id).列(“AccountID”); Map(x=>x.AccountNumber); HasMany(x=>x.Transactions) //这里用什么来解释NHibernate的映射? .Inv
公共类AccountMap:子类映射
{
公共帐户映射()
{
Id(x=>x.Id).列(“AccountID”);
Map(x=>x.AccountNumber);
HasMany(x=>x.Transactions)
//这里用什么来解释NHibernate的映射?
.Inverse().Cascade.AllDeleteOrphan()
.Access.CamelCaseField();
}
}
注意:我知道我可以将交易映射为两个单独的集合,一个用于“借项”,另一个用于“贷项”。由于性能问题,这不是一个可接受的答案。特别是,实际上还有第二种类型与帐户(导致更多查询)和映射相关,因为两个集合阻止了使用Fetch()
进行即时加载。第二种类型是PaymentScheduleLine
,它包含帐户生命周期内所有正确付款交易的计划。它以与交易相同的方式与账户关联,即PaymentScheduleLine
具有DebitAccount
和CreditAccount
和account
具有PaymentSchedule
收款。通常,复杂的计算涉及交易和付款计划之间的关系。我可能会在听到更多关于“与资产相关的第二种类型”的信息后修改我的答案,但现在
决定什么是重要的,并愿意做出牺牲。
听起来性能是你最关心的,对吗?您可能需要放宽您的要求,不要更改域模型,或者让查询以某种方式显示
使用.Future()
进行批查询,以避免笛卡尔积。
您是对的,将集合命名为借方
和贷方
可能会导致性能问题。也许这就是你想问的问题:
// BAD QUERY - DO NOT USE - cartesian product of rows - Debits X Credits.
var account = session.QueryOver<Account>()
.Fetch(x => x.Debits).Eager
.Fetch(x => x.Credits).Eager
.Where(x => x.Id == accountId)
.SingleOrDefault();
。。。可以轻松地将您处理的交易数量从1000减少到20或更少。如果我听到更多关于“与资产相关的第二种类型”,我可能会修改我的答案,但现在
决定什么是重要的,并愿意做出牺牲。
听起来性能是你最关心的,对吗?您可能需要放宽您的要求,不要更改域模型,或者让查询以某种方式显示
使用.Future()
进行批查询,以避免笛卡尔积。
您是对的,将集合命名为借方
和贷方
可能会导致性能问题。也许这就是你想问的问题:
// BAD QUERY - DO NOT USE - cartesian product of rows - Debits X Credits.
var account = session.QueryOver<Account>()
.Fetch(x => x.Debits).Eager
.Fetch(x => x.Credits).Eager
.Where(x => x.Id == accountId)
.SingleOrDefault();
。。。可以轻松地将您处理的事务数量从1000减少到20或更少。我知道他的答案是映射到两个不同的集合,这是不可接受的。然而,我也知道答案是修改域,这在这里是不可接受的。作为旁注,这似乎是一个奇怪的会计数据结构,因为一个典型的会计交易可能会影响两个或多个帐户。这当然意味着需要进一步规范您的数据结构,但您在这里面临的问题将消失。我知道,在许多情况下,会计涉及Martin Fowler在其《分析模式》一书中所称的“多腿”交易。我们以前有过这个模型,发现它太复杂了。我们采用DDD方法,在我们的特定领域,所有交易仅涉及两个账户。当我们将数据库规范化为事务和条目时,我们实际上遇到了严重的性能问题,代码也不必要地复杂。很难回答这样一个问题:在给定的时间段内,有多少资金从a账户转移到B账户。您能否在示例中添加“与资产相关的第二种类型”?谢谢。我已经在便条下面添加了更多关于“第二种类型与此帐户相关”的信息。我不想把主要的例子弄得乱七八糟,但我知道他的答案是映射到两个不同的集合,这是不可接受的。然而,我也知道答案是修改域,这在这里是不可接受的。作为旁注,这似乎是一个奇怪的会计数据结构,因为一个典型的会计交易可能会影响两个或多个帐户。这当然意味着需要进一步规范您的数据结构,但您在这里面临的问题将消失。我知道,在许多情况下,会计涉及Martin Fowler在其《分析模式》一书中所称的“多腿”交易。我们以前有过这个模型,发现它太复杂了。我们采用DDD方法,在我们的特定领域,所有交易仅涉及两个账户。当我们将数据库规范化为事务和条目时,我们实际上遇到了严重的性能问题,代码也不必要地复杂。很难回答这样一个问题:在给定的时间段内,有多少资金从a账户转移到B账户。您能否在示例中添加“与资产相关的第二种类型”?谢谢。我已经在便条下面添加了更多关于“第二种类型与此帐户相关”的信息。我不想把主要的例子弄乱。丹尼尔,谢谢你提供的宝贵信息。不幸的是,我正处于一个充满挑战的境地。我们即将发布产品,我们已经有了这个域模型(我们实际上有借项和贷项集合,然后将这些集合合并到事务集合中)。这不是一个信号
SELECT ...
FROM [Transaction]
WHERE DebitAccountID=@accountID OR CreditAccountID=@accountID
public class AccountMap : SubclassMap<Account>
{
public AccountMap()
{
Id(x => x.Id).Column("AccountID");
Map(x => x.AccountNumber);
HasMany(x => x.Transactions)
// What goes here to explain this mapping to NHibernate?
.Inverse().Cascade.AllDeleteOrphan()
.Access.CamelCaseField();
}
}
// BAD QUERY - DO NOT USE - cartesian product of rows - Debits X Credits.
var account = session.QueryOver<Account>()
.Fetch(x => x.Debits).Eager
.Fetch(x => x.Credits).Eager
.Where(x => x.Id == accountId)
.SingleOrDefault();
var futureAccount = session.QueryOver<Account>()
.Fetch(x => x.Debits).Eager
.Where(x => x.Id == accountId)
.FutureValue();
session.QueryOver<Account>()
.Fetch(x => x.Credits).Eager
.Where(x => x.Id == accountId)
.Future();
var account = futureAccount.Value;
var transactions = session.QueryOver<Transaction>()
.Where(x => x.DebitAccount.Id == fromId
&& x.CreditAccount.Id == toId
&& x.Date >= startDate
&& x.Date < endDate.AddDays(1))
.List();