持久性规范和逆

发布于 2024-12-06 04:53:49 字数 1979 浏览 0 评论 0原文

我很早之前就已经在 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 行为是一个错误。

谢谢。

I've already posted this in the Fluent NH group a long time ago, but didn't get any answers until today. SO, here's the problem: I've got a one-to-many relationship defined and the one side has the inverse flag set. the mapping code looks something like this:

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();
    }
}

Now, Imagem's mapping looks like this:

 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();
    }
}

And here's the code that tests the persistence of these classes:

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

Even though Inverse is "on", PersistenceSpecification tries to insert Imagem before inserting Receita. Since IdReceita is foreign key configured not to accept null, I end up with an exception. I've tried writing "real world code" that uses receita and it works (I've turned on SQL and I can see that in this case, Receita is inserted before Imagem as it should be).

Since nobody answered this question on FH group, I was wondering if someone can please confirm that this PersistenceSpecification behavior is a bug.

thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

晨与橙与城 2024-12-13 04:53:49

你试过这样吗?:

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

Have you tried it this way?:

var receita = BuildMeAReceita();
var imagems = BuildSomeImagems();
foreach(var imagem in imagems){
    receita.AdicionaImagem(imagem);
}
new PersistenceSpecification<Receita>(sess)
.VerifyTheMappings(receita);
酒解孤独 2024-12-13 04:53:49

尝试:

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

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

Try:

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

My guess is that your real world code saves Recieta first so that the inserts are issued in the correct order. If you changed that code to save Imagem first you would get the same error because NHibernate would attempt to insert Imagem then update it with the foreign key.

雨轻弹 2024-12-13 04:53:49

您可以更改 Imagem 的映射,

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

这将在 Imagem 之前保留 Receita

我发现 PersistanceSpecification 有效对于相当直接的关系来说很好,但如果您有复杂的对象图,则必须对所有对象启用级联。不过,您的场景相当简单,因此这个小更改应该允许您使用 PersistanceSpecification 进行测试。

编辑:

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

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

You could change your mapping of Imagem

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

This will persist Receita before Imagem

What I've found is that PersistanceSpecification works well for fairly straight forward relationships but if you have complex object graphs you have to have cascading turned on all of your objects. Your scenario is fairly simple though so this small change should allow you to test this using PersistanceSpecification.

Edit:

Also make sure in your AdicionaImagem function you are setting the parent of the image. Here is an example:

public virtual void AdicionaImagem(Imagem newImagem)
{
    newImagem.Receita = this;
    imagems.Add(newImagem);
}
落花随流水 2024-12-13 04:53:49

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

  1. Imagem.Bytes 属性是延迟加载的,但对于 Imagem 是延迟加载的
    自己已被禁用。这意味着没有为 Imagem 生成代理
    实例和字节不能延迟加载:不可能完成的任务(至少现在在我看来,不确定)。
    从数据库简单加载 (session.Get(id);) 会导致
    像这样的例外:
    无效的转换(检查您的映射是否属性类型不匹配); Imagem 的设置者
    解决方案是在 Imagem 上启用延迟加载或在 Bytes 属性上禁用延迟加载。
  2. PersistenceSpecification 从数据库加载测试实体 as
    另一个实例
    。这意味着默认的相等比较器不
    工作顺利。您需要提供自己的相等比较器来解决
    这个问题(查看更多详细信息)。

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

There are two possible issues in your code.

  1. Imagem.Bytes property is lazy-loaded but lazy loading for Imagem
    istself is disabled. It means no proxy is generated for Imagem
    instances and Bytes cannot be lazy-loaded: mission impossible (at least it appears to me right now, not sure).
    Simple load from database (session.Get<Imagem>(id);) leads to
    exceptions like this:
    Invalid Cast (check your mapping for property type mismatches); setter of Imagem.
    Solution is to enable lazy-loading on Imagem or disable lazy loading on Bytes property.
  2. PersistenceSpecification loads tested entity from database as
    another instance
    . It means that default equality comparer does not
    work well. You need to provide your own equality comparer to solve
    this issue (check this for more details).

Here is Receita and Imagem entities, implementation of IEqualityComparer and PersistentSpecification snippet. This code works well in NH3.1 and FNH 1.2. Please, let me know if your code differs somehow from these snippets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文