Невозможно сохранить новый объект в отношениях один к одному - PullRequest
1 голос
/ 16 сентября 2011

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

Вот мой класс сайта (важные биты)

public class Site : CoreObjectBase
{
    public virtual int SiteId { get; set; }
    public virtual WebOptions WebOptions { get; set; }
}

А вот мой класс веб-опций (снова важные части)

public class WebOptions : CoreObjectBase
{
    public virtual int WebOptionsId { get; set; }

    private int SiteId { get; set; }
    private Site Site { get; set; }
}

А отображение для Site равно

HasOne<WebOptions>(x => x.WebOptions)
    .Cascade.All();

А отображение для WebOptions равно

Id(Reveal.Property<WebOptions>("SiteId")).GeneratedBy.Foreign("Site");
HasOne<Site>(Reveal.Member<WebOptions, Site>("Site"))
    .Constrained()
    .ForeignKey();

В данных таблица за сайтом не имеет поля foreighn для WebOptions, но таблица за WebOptions содержит идентификатор SiteId. В моем коде я уже получаю сайт и использую site.WebOptions.SomeSetting и хотел бы сохранить его таким.

Моя проблема в этом. Если я вообще отклоняюсь от этого сопоставления, мои разрывы модели и никакие веб-варианты не возвращаются, в то время как несколько записей сохраняются в таблице веб-вариантов (дубликаты). Но когда я пытаюсь сохранить новый объект WebOptions, я получаю

Пакетное обновление вернуло неожиданное количество строк от обновления; фактическая строка количество: 0; ожидается: 1

У меня есть класс репозитория с двумя методами сохранения:

public sealed class Repository<T> : IRepository<T> where T : CoreObjectBase
{
    public void SaveWithDependence<K>(T entity, K dependant) where K : CoreObjectBase
    {
        entity.Validate();
        dependant.Validate();

        using (ITransaction tx = Session.BeginTransaction())
        {
            Session.SaveOrUpdate(entity);
            Session.SaveOrUpdate(dependant);
            tx.Commit();
        }
    }

    public void Save(T entity)
    {
        entity.Validate();

        using (ITransaction tx = Session.BeginTransaction())
        {
            Session.SaveOrUpdate(entity);
            tx.Commit();
        }
    }
}

Когда WebOptions не найдено, я делаю это при создании нового:

var options = site.WebOptions;

if (options == null)
{
    options = new WebOptions(site);
    site.WebOptions = options;
}

И конструктор выглядит так, чтобы установить частные переменные

public WebOptions(Site site)
{
    Site = site;
    SiteId = site.SiteId;
}

А потом, чтобы сохранить, я попытался следующее:

siteRepository.Save(site);

и

siteRepository.SaveWithDependence(site, options);

и

optionsRepository.Save(options);
* * И тысяча сорок-девять
optionsRepository.SaveWithDependence<Site>(options, site);

Все они возвращают вышеуказанную ошибку. Моя сессионная декларация выглядит так

sessionFactory =  
            Fluently.Configure().Database(
                FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005.DefaultSchema("dbo")
                    .ConnectionString(c => c
                        .FromConnectionStringWithKey("MyDatabase"))
                        .AdoNetBatchSize(20))
                    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<SessionManager>())
                    .ExposeConfiguration(x => x.SetProperty("current_session_context_class", "managed_web"))
                    .BuildSessionFactory();

Мне действительно нужно иметь возможность сохранить новую запись WebOptions, если она не существует, но я не могу заставить ее работать с моими отношениями один на один.

1 Ответ

1 голос
/ 16 сентября 2011

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

В конструкторе для WebOptions Я удалилэта строка:

SiteId = site.SiteId;

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

public WebOptions(Site site)
{
    Site = site;
}

Затем я сохраняю только свой WebOptions объект, подобный этому:

optionsRepository.Save(options);

Мое лучшее предположение состоит в том, что, поскольку я использую поле идентификатора для свойства «SiteId» в свободном языке, свободное владение не позволяет мне устанавливать это значение вручную.Установка частного свойства Site в дополнение к настройке свойства Site.WebOptions должна установить отношение «один к одному» для fluent / nhibernate, чтобы определить, какое значение следует поместить в поле SiteId.

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

Открытый конструктор , принимающий параметр Client, - это тот, который вы будете использовать в своем коде, когда захотитеназначить клиенту некоторые пищевые привычки, такие как: AlimentaryHabits = new AlimentaryHabits(this);.Защищенный конструктор используется внутри NHibernate и должен присутствовать.Вы можете полностью игнорировать это.

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

...