Вставить в дочернюю таблицу с помощью NHibernate 2.0.1 - PullRequest
0 голосов
/ 17 апреля 2009

Я начал использовать NHibernate на этой неделе (изо всех сил). У меня есть небольшое приложение с 3 таблицами (сейчас я использую 2). Таблица currency и таблица country - это файлы сопоставления.

<class name="dataprovider.Country,dataprovider" table="country">
    <id name="CountryId" column="country_id" unsaved-value="0">
        <generator class="native"/>
    </id>
    <!--<bag name="BatchList" inverse="true" lazy="true" >
        <key column="country_id" />
        <one-to-many class="Batch" />
    </bag>
    <bag name="PrinterList" inverse="true" lazy="true" >
        <key column="country_id" />
        <one-to-many class="Printer" />
    </bag>-->
    <many-to-one name="CurrencyId" column="currency_id" class="Currency"  cascade="save-update"/>
    <!--<property column="currency_id" name="Currency_Id"/>-->
    <property column="name" name="Name"/>
    <property column="region" name="Region" />
    <property column="comments" name="Comments"/>
</class>

Файл отображения валюты:

<class name="dataprovider.Currency, dataprovider" table="currency">
    <id name="CurrencyId" column="currency_id" >
        <generator class="native"/>
    </id>
    <bag name="CountryList" inverse="true" lazy="true" >
        <key column="currency_id" />
        <one-to-many class="Country" />
    </bag>
    <!--<bag name="DenominationList" inverse="true" lazy="true" >
        <key column="currency_id" />
        <one-to-many class="Denomination" />
    </bag>-->
    <property column="name" name="Name"/>
    <property column="authorizer" name="Authorizer"  />
    <property column="date_created"  name="DateCreated" type="DateTime" not-null="true" />
    <property column="comments"  name="Comments"  />

Отношение «многие к одному», которое удерживается country, создает атрибут типа Currency в классе персистентности country. Теперь, когда мои тесты can_add_currency и can_add_country выполнены успешно (я экспортирую схему), в таблице country для поля currency_id.

указано нулевое значение.

Вот код теста:

[Test]
    public void can_add_new_country()
    {
        CountryManager cm = new CountryManager();

        Country country = new Country();
        //country.CurrencyId = CurrencyManager.GetCurrencyById(1);
        country.CurrencyId = new CurrencyManager().GetCurrencyById(1);
        country.Name = "POUND";
        country.Region = "ENGLAND";
        country.Comments = "the comment";

        cm.Add(country);

        using(ISession session = _sessionFactory.OpenSession())
        {
            Country fromdb = session.Get<Country>(country.CountryId);
            Assert.IsNotNull(fromdb);
            Assert.AreNotSame(fromdb, country);
        }
    }

    public Currency GetCurrencyById(int currency_id)
    {//GetCurrencyById from CurrencyManger class
        try
        {
            using(ISession session = NHibernateHelper.OpenSession())
            {
                return session.Get<Currency>(currency_id);

            }
        } catch (Exception ex)
        {
            return null;
        }
    }

Вопрос в следующем: как вставить в таблицу country с помощью currency_id существующего currency_id из валюты таблицы ?

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

Ответы [ 2 ]

0 голосов
/ 18 апреля 2009

Мой каскад был скорее на этой стороне:

<many-to-one name="CurrencyId" column="currency_id" class="Currency"  cascade="save-update"/>

После того, как я изменил его, сначала он не работал, хотя я перестраивал решение. Затем я сделал еще один тест из класса Currency_Test: can_get_currency_by_id, который вызывает ту же функцию GetCurrncyById, и у меня мог быть объект, в то время как из can_add_new_country та же функция возвращает ноль.

Затем я понимаю, что ExportSchema либо Country_Test [Setup], либо Currency_Test не создает базу данных вовремя, чтобы can_add_new_product имел объект валюты. Вот почему он возвращает нулевой объект.

Теперь не злоупотребляйте; но можете ли вы сказать мне, как использовать IList<Counrty>CountryList? Я не знаю, правильно ли я это сформулировал. Насколько я понимаю, он должен хранить все country объекты, используя один и тот же currency (ссылка currency_id). Как NHibernate делает это?

0 голосов
/ 18 апреля 2009

Установите cascade="save-update" на вашем bag name="CountryList". Если это не сработает, может быть полезно опубликовать свой код для CountryManager.Add(), чтобы увидеть, как происходит сохранение.

В ответ на ваш второй вопрос, если я правильно понял, вот как NHibernate относится к отображенным коллекциям:

Вы отобразили коллекцию как ленивую, поэтому при загрузке объекта не загрузит все элементы коллекции одновременно. Вместо этого при первом доступе к коллекции NHibernate запросит базу данных, чтобы заполнить коллекцию и вернуть ее. Итак, когда вы впервые делаете что-то вроде:

var countries = currency.CountryList;

или

foreach (Country country in currency.CountryList)

NHibernate автоматически выполнит запрос, подобный следующему:

SELECT * FROM country WHERE currency_id = ?

А затем создайте коллекцию объектов Country для возврата (и кэшируйте, чтобы запрос больше не запускался).

По сути, с помощью файла сопоставления вы уже рассказали NHibernate обо всех ваших сущностях (Страна и Валюта) и о том, как они связаны, чтобы он знал, как создавать запросы для доступа к данным. Точно так же он отслеживает то, что было в коллекции, поэтому при добавлении или удалении элементов он может сравнивать то, что было изменено, и выполнять соответствующие операторы INSERT или REMOVE.

Таким образом, способ использования коллекций, отображаемых с помощью NHibernate, состоит в том, чтобы использовать их так же, как и в обычной коллекции .NET. Добавить и удалить элементы по вашему желанию. Как только вы закончите, убедитесь, что вы сказали NHibernate, чтобы сохранить изменения, внесенные в базу данных, вызвав session.Save() или session.Delete() для каждого добавляемого / удаляемого элемента или (если вы установили каскадирование, как вы сделали) простой вызов session.Save() для родительского объекта, который содержит коллекцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...