Совокупный обход NHibernate (C #) - PullRequest
4 голосов
/ 08 июня 2009

У моего приложения сейчас очень простая модель, и я пытаюсь найти лучший способ прохождения через агрегат. Как вы можете видеть на моей схеме модели внизу, у меня есть учетная запись, поездка и список людей, посещающих поездку. Я хотел бы иметь возможность просматривать все поездки, к которым относится отдельная учетная запись, и я придумал что-то вроде этого:

    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

Ответы [ 3 ]

3 голосов
/ 09 июня 2009

Я не удивлен, это не кажется тебе правильным, не так. На самом деле, это так неправильно, это больно! Но вместо того, чтобы просто причинять вам горе, я объясню все причины, по которым это неправильно @

Во-первых, ваша загрузка во ВСЕХ обращениях в память из базы данных, по сути, означает, что вы запрашиваете хранилище данных, чтобы получить целую загрузку ненужных вам данных, а затем передаете их по проводам. Это хорошо, если у вас есть несколько поездок, но это не будет масштабироваться вообще.

Далее вы повторяете каждую поездку и называете свойство "trip.People". Затем он снова попадет в базу данных и загрузит ВСЕ данные для людей в КАЖДОМ из этих рейсов. Опять же, это убьет вас, если у вас будет несколько поездок с несколькими посетителями. Теперь это предполагает, что у вас нет фильтров в ваших сопоставлениях, или вы специально попросили NHibernate не выполнять отложенную загрузку вашей коллекции People, но в любом случае это целая загрузка данных, которую вы не хотите.

Мой совет - взглянуть на документы NHibernate, касающиеся запросов к вашей объектной модели с использованием HQL или Linq-To-NHibernate, и вы получите запросы, которые выглядят примерно так:

HQL (МОЙ HQL Отстой, так что это может быть очень неправильно):

var hql = @ "от Trip as t присоединиться к т. люди как р с p.Account.Id =: accountId выберите t "

Edit:

На самом деле, мой мозг сейчас немного медленный, поскольку уже поздно, но я только что понял, что вы делаете что-то здесь немного назад. Что вы на самом деле делаете после того, как все поездки, которые совершил человек, так почему бы вашему объекту учетной записи не сопоставить коллекцию поездок? По сути, вы должны стремиться к чему-то вроде этого:

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

Edit:

Опять я устал, так что это может быть чепухой, но я думаю, что карта, которую вы ищете, будет выглядеть так:

    <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 as tp Где tp.Account.Id =: accountId AND tp.IsActive = true выберите tp.Trip "

Перестану отвечать сейчас, пока я не сделал более глупые вещи.

1 голос
/ 09 июня 2009

спасибо за вашу помощь. Я думаю, я понял прошлой ночью, чего я пытался достичь. Я не совсем уверен, что это лучший способ, но пока он работает хорошо. Я смог придумать интерфейс, подобный следующему:

//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);

Чтобы достичь этого, я создал таблицу «многие ко многим», в которой хранятся первичные ключи от «Пользователь» и «Поездка», а затем сопоставил отношение в NHibernate с классом пользователя и классом поездки. Также, чтобы получить статус пользователя для поездки, я создал сущность, которая хранит состояние пользователя вместе с поездкой и информацией о пользователе. Кажется, это небольшое дублирование данных, но мне нравится, как оно работает и выглядит в настоящее время.

Если у вас, ребята, есть какие-либо комментарии или лучший способ реализовать это, дайте мне знать. Я всегда готов что-то улучшить! Еще раз спасибо

alt text

0 голосов
/ 09 июня 2009

То, что сказал Оуэн, может быть лучшим способом сделать это, если вы не загрузили свои поездки до того, как включили этот метод.

То, что я предлагаю, - это создать какой-то метод сравнения () для класса. Список поездок

Поездки в открытом классе: список <Поездка> {

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 () класса объекта

...