PersistenceSpecification и обратный - PullRequest
       24

PersistenceSpecification и обратный

2 голосов
/ 24 сентября 2011

Я уже опубликовал это в группе Fluent NH давным-давно, но до сегодняшнего дня не получил никаких ответов.Итак, вот проблема: у меня определено отношение «один ко многим», а на одной стороне установлен обратный флаг.код отображения выглядит примерно так:

public class MapeamentoReceita : ClassMap<Receita> {
    public MapeamentoReceita() {
        Table("Receitas");
        Not.LazyLoad();

        Id(rec => rec.Id, "IdReceita")
            .GeneratedBy
            .HiLo("TabelaHilo", "ProximoHi", "1000", "Tabela='receitas'")
            .Default(0);
        Version(rec => rec.Versao);

        //other props go here
        HasMany(rec => rec.Imagens)
            .Access.CamelCaseField((Prefix.Underscore))
            .AsBag()
            .Cascade.All()
            .KeyColumn("IdReceita")
            .Not.LazyLoad()
            .Inverse();
    }
}

Теперь отображение Imagem выглядит следующим образом:

 public class MapeamentoImagem : ClassMap<Imagem> {
    public MapeamentoImagem() {
        Table("Imagens");
        Not.LazyLoad();
        Id(img => img.Id, "IdImagem")
            .GeneratedBy
            .HiLo("TabelaHiLo", "ProximoHi", "1000", "Tabela='imagens'")
            .Default(0);
        Map(img => img.Bytes)
            .CustomSqlType("image")
            .CustomType<Byte[]>()
            .LazyLoad()
            .Length(2000000000)
            .Not.Nullable()
            .Not.Update();

        References(img => img.Receita)
            .Column("IdReceita")
            .Cascade.None();
    }
}

А вот код, который проверяет постоянство этих классов:

 new PersistenceSpecification<Receita>(sess)
    .CheckList(rec => rec.Imagens, 
               _imagens, 
               (receita, imagem) => receita.AdicionaImagem(imagem))
    .VerifyTheMappings();

Несмотря на то, что Inverse «включен», PersistenceSpecification пытается вставить Imagem перед вставкой Receita.Так как IdReceita - это внешний ключ, настроенный не принимать ноль, я получаю исключение.Я попытался написать «код реального мира», который использует Receita, и он работает (я включил SQL, и я вижу, что в этом случае Receita вставляется перед Imagem, как и должно быть).

Так какникто не ответил на этот вопрос о группе FH, мне было интересно, если кто-нибудь может подтвердить, что это поведение PersistenceSpecification является ошибкой.

спасибо.

Ответы [ 4 ]

3 голосов
/ 01 октября 2011

Вы пробовали это так?:

var receita = BuildMeAReceita();
var imagems = BuildSomeImagems();
foreach(var imagem in imagems){
    receita.AdicionaImagem(imagem);
}
new PersistenceSpecification<Receita>(sess)
.VerifyTheMappings(receita);
0 голосов
/ 05 октября 2011

В вашем коде есть две возможные проблемы.

  1. Imagem.Bytes свойство загружено с отложенной загрузкой, но отложенная загрузка для Imagem отключена.Это означает, что прокси-сервер не генерируется для Imagem экземпляров и Байт не может быть загружен из-за ленивости: миссия невыполнима (по крайней мере, мне это кажется сейчас, не уверен).Простая загрузка из базы данных (session.Get<Imagem>(id);) приводит к таким исключениям: Invalid Cast (check your mapping for property type mismatches); setter of Imagem.Решение состоит в том, чтобы включить отложенную загрузку в Imagem или отключить отложенную загрузку для свойства Bytes .
  2. PersistenceSpecification загружает проверенный объект из базы данных как другой экземпляр .Это означает, что компаратор равенства по умолчанию не работает.Вы должны предоставить свой собственный компаратор равенства для решения этой проблемы (проверьте это для более подробной информации).

Здесь есть Receita и Imagem сущностей, реализация IEqualityComparer и PersistentSpecification фрагмент.Этот код хорошо работает в NH3.1 и FNH 1.2.Пожалуйста, дайте мне знать, если ваш код чем-то отличается от этих фрагментов.

0 голосов
/ 30 сентября 2011

Вы можете изменить свое отображение на Imagem

References(img => img.Receita)
            .Column("IdReceita")
            .Cascade.SaveUpdate();

Это будет сохраняться Receita до Imagem

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

Edit:

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

public virtual void AdicionaImagem(Imagem newImagem)
{
    newImagem.Receita = this;
    imagems.Add(newImagem);
}
0 голосов
/ 24 сентября 2011

Попробуйте:

    References(img => img.Receita)
        .Column("IdReceita")
        .Not.Nullable();

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

...