使用Fluent NHibernate映射由两列之一连接的集合?

使用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

我正在建立会计模型,其中我的账户有借记一个账户,贷记另一个账户的交易

以下是详细情况(简化)。我的表(在SQL Server 2008中)是:

我的课程是:

where子句中的重要部分是

所以我需要的代码是:

公共类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();