2

很久以前我已经在 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 也会尝试在插入 Receita 之前插入 Imagem。由于 IdReceita 是配置为不接受 null 的外键,因此我最终遇到了异常。我已经尝试编写使用 receita 的“真实世界代码”并且它可以工作(我已经打开了 SQL,我可以看到在这种情况下,Receita 应该插入到 Imagem 之前)。

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

谢谢。

4

4 回答 4

3

你试过这样吗?:

var receita = BuildMeAReceita();
var imagems = BuildSomeImagems();
foreach(var imagem in imagems){
    receita.AdicionaImagem(imagem);
}
new PersistenceSpecification<Receita>(sess)
.VerifyTheMappings(receita);
于 2011-09-30T21:30:06.930 回答
0

尝试:

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

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

于 2011-09-24T13:35:14.037 回答
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);
}
于 2011-09-30T01:21:09.187 回答
0

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

  1. Imagem.Bytes属性是延迟加载的,但Imagem本身的延迟加载 被禁用。这意味着没有为Imagem 实例生成代理,并且Bytes不能被延迟加载:任务不可能(至少现在在我看来,不确定)。从数据库 ( ) 的简单加载session.Get<Imagem>(id);会导致如下异常: Invalid Cast (check your mapping for property type mismatches); setter of Imagem. 解决方案是在 Imagem 上启用延迟加载或在Bytes属性上禁用延迟加载。
  2. PersistenceSpecification 从数据库加载测试实体作为另一个实例。这意味着默认的相等比较器不能很好地工作。您需要提供自己的相等比较器来解决此问题(查看此以获取更多详细信息)。

这是ReceitaImagem实体,IEqualityComparerPersistentSpecification片段的实现。此代码在 NH3.1 和 FNH 1.2 中运行良好。请让我知道您的代码是否与这些片段有所不同。

于 2011-10-04T21:18:45.370 回答