PersistenceSpecification和反向

时间:2011-09-24 11:44:03

标签: nhibernate collections fluent-nhibernate inverse

很久以前我已经在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处于“on”状态,PersistenceSpecification也会在插入Receita之前尝试插入Imagem。由于IdReceita是外键配置为不接受null,我最终得到一个例外。我已经尝试编写使用receita的“真实世界代码”并且它有效(我已经打开了SQL,我可以看到在这种情况下,Receita会在Imagem之前插入它应该是这样)。

由于没有人在FH小组回答这个问题,我想知道是否有人可以确认此PersistenceSpecification行为是一个错误。

感谢。

4 个答案:

答案 0 :(得分:3)

你有没有尝试过这种方式?:

var receita = BuildMeAReceita();
var imagems = BuildSomeImagems();
foreach(var imagem in imagems){
    receita.AdicionaImagem(imagem);
}
new PersistenceSpecification<Receita>(sess)
.VerifyTheMappings(receita);

答案 1 :(得分:0)

尝试:

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

我的猜测是你的真实世界代码首先保存Recieta,以便以正确的顺序发出插入。如果您更改了该代码以首先保存Imagem,则会出现相同的错误,因为NHibernate将尝试插入Imagem,然后使用外键更新它。

答案 2 :(得分:0)

您可以更改Imagem

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

这将在Receita

之前保留Imagem

我发现PersistanceSpecification适用于相当直接的关系,但如果您有复杂的对象图,则必须打开所有对象的级联。您的方案非常简单,但是这个小的更改应该允许您使用PersistanceSpecification进行测试。

编辑:

还要确保在AdicionaImagem功能中设置图像的父级。这是一个例子:

public virtual void AdicionaImagem(Imagem newImagem)
{
    newImagem.Receita = this;
    imagems.Add(newImagem);
}

答案 3 :(得分:0)

您的代码中存在两个可能的问题。

  1. Imagem.Bytes 属性是延迟加载但延迟加载 Imagem 自己被禁用了。这意味着没有为 Imagem 生成代理 实例和字节不能延迟加载:任务不可能(至少在我现在看来,不确定)。 数据库(session.Get<Imagem>(id);)的简单加载导致 像这样的例外: Invalid Cast (check your mapping for property type mismatches); setter of Imagem。 解决方案是在Imagem上启用延迟加载或禁用字节属性上的延迟加载。
  2. PersistenceSpecification从数据库as another instance加载经过测试的实体。这意味着默认的相等比较器没有 工作得很好。您需要提供自己的相等比较器来解决 这个问题(请查看此内容以获取更多详细信息)。
  3. 以下是ReceitaImagem个实体,IEqualityComparerPersistentSpecification代码段的实现。此代码适用于NH3.1和FNH 1.2。如果您的代码与这些代码段有所不同,请告诉我。