NHibernate聚合遍历(C#)

问题描述 投票:4回答:3

我的应用程序现在有一个非常简单的模型,我正在尝试找到遍历聚合的最佳方法。正如您在底部的模型图中所看到的,我有一个帐户,一个旅行和一个参加旅行的人员列表。我希望能够查看帐户所涉及的所有旅行,我想出了类似这样的事情:

    public List<Trip> GetAllTripsFor(int accountid)
    {
        var tripRepository = new TripRepository();
        var trips = tripRepository.FindAll();
        var userTrips = new List<Trip>();

        foreach (Trip trip in trips)
        {
            foreach (TripPeople person in trip.People)
            {
                // If this trip's person list contains this accountid
                // then add this trip to the userTrips list.
                if(person.Account.Id == accountid)
                    userTrips.Add(trip);
            }
        }

        return userTrips;
    }

对我而言,这似乎不是很有效,而且我没有正确地思考问题。你们有没有想过更好的实现方法?也许我在想我的模特错了?谢谢

alt text

c# nhibernate domain-driven-design aggregate traversal
3个回答
3
投票

我并不感到惊讶,这对你感觉不对,不是。事实上它是如此错误的伤害!但不仅仅是让你悲伤生病解释所有这个错误的原因@

首先,您从数据库中进入内存的所有行程中的负载,这实际上意味着您正在查询数据存储以获取您不需要的整个数据负载,然后将其传递给线路。如果您有几次旅行,这很好,但这根本不会扩展。

接下来,您将通过每次旅行递归并致电酒店“trip.People”。然后,这将再次访问数据库,并在其中一个行程中为人们加载所有数据。同样,如果您与多位与会者进行多次旅行,这将会扼杀您。现在,假设您的映射没有过滤器,或者您明确要求NHibernate不要延迟加载您的People集合,但无论哪种方式都是您不想要的全部数据。

我的建议是查看有关使用HQL或Linq-To-NHibernate查询对象模型的NHibernate文档,最终会得到如下所示的查询:

HQL(我的HQL糟透了所以这可能是非常错误的):

var hql = @“from Trip as t join t.People as p with p.Account.Id =:accountId select t”

编辑:

实际上,我的大脑现在有点慢,因为它已经很晚了,但我刚才意识到你的做法有点倒退。你实际上所经历的是一个人一直在旅行的所有行程,那么为什么你的帐户对象没有映射到的Trips集合呢?你本质上应该瞄准这样的事情:

var trips = accountRepo.GetAccount(123).Trips;

编辑:

我很累,所以这可能是无稽之谈,但我认为您正在寻找的映射将如下所示:

    <bag name="Trip"  cascade="all" table="TripToAccount" lazy="true">
        <key column="AccountId" />
        <many-to-many class="Trip">
            <column name="TripId" not-null="true"/>
        </many-to-many>
    </bag>

编辑:

该死的,我应该去睡觉了。现在我看到你已经有人和他们的旅行之间的映射,所以为什么不:

var query =“from TripPeople as tp where tp.Account.Id =:accountId AND tp.IsActive = true select tp.Trip”

在我做更多愚蠢的事情之前,现在停止回答。


1
投票

谢谢你的帮助。我想我昨晚想出了我想要实现的目标。我不完全确定这是最好的方法,但到目前为止它还是很好用。我能够提出如下界面:

//Return a list of trips for the user
var user = accountRepository.GetUserBy(123);
var userTrips = user.Trips;

//Return all of the users attending a trip
var peopleAttendingTrip = tripRepository.GetTripBy(234).People;

//Check user's status for a trip. A user must pay some kind of deposit
//before they are considered active.
var userStatus = userTrips.SingleOrDefault().GetStatusFor(user);

为了实现这一点,我创建了一个多对多表,其中包含来自User和Trip的主键,然后将NHibernate中的关系映射到User Class和Trip Class。此外,为了实现用户的旅行状态,我创建了一个实体,用于存储用户的状态以及旅行和用户信息。这似乎是一些重复的数据,但我喜欢它目前的工作方式和外观。

如果你们有任何意见或更好的方式来实现这一点,请告诉我。我总是想要改进一些东西!再次感谢

alt text


0
投票

如果你在使用这种方法之前没有加载你的行程,那么欧文所说的可能是最好的方法。

我建议的是为类的旅行列表构建某种compare()方法

public class Trips:List <Trip> {

public Trips()
{
    //
    // TODO :
    //
}


#region methods

/// <summary>
/// return trip
/// </summary>

public Trip FindTrip(int accountId)
{
    return this.Find(delegate(trip t) {
    return t.AccountId == accountId; });
}
#end region 

}

我不能确定它是否是最好的,但这就是我的方式hahan haha​​n它就像对象类的Find()方法

© www.soinside.com 2019 - 2024. All rights reserved.