4

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

    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;
    }

对我来说,这似乎不是很有效,而且我没有正确地思考事情。你们中的任何人对实现这一点的更好方法有什么想法吗?也许我在想我的模型错了?谢谢

替代文字

4

3 回答 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"

编辑:

其实,我现在的大脑有点迟钝了,但我才意识到你在这里做的事情有点倒退。你真正追求的是一个人的所有旅行,那么为什么你的帐户对象没有映射到的旅行集合呢?你应该基本上瞄准这样的事情:

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 = "从 TripPeople 作为 tp where tp.Account.Id = :accountId AND tp.IsActive = true select tp.Trip"

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

于 2009-06-08T21:52:19.470 回答
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。此外,为了获得用户的旅行状态,我创建了一个实体,用于存储用户的状态以及旅行和用户信息。这看起来有点重复数据,但我喜欢它目前的工作方式和外观。

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

替代文字

于 2009-06-09T17:06:12.313 回答
0

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

我的建议是为类 List of trips 构建某种 compare() 方法

公共类旅行:列表<旅行> {

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 

}

我不能确定它是否是最好的,但我就是这样做的,哈哈,这就像对象类的 Find() 方法

于 2009-06-08T22:07:22.530 回答