持久性规范和逆
我很早之前就已经在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你试过这样吗?:
Have you tried it this way?:
尝试:
我的猜测是,您的现实世界代码首先保存 Recieta,以便以正确的顺序发出插入。如果您更改该代码以首先保存 Imagem,您将收到相同的错误,因为 NHibernate 会尝试插入 Imagem,然后使用外键更新它。
Try:
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.
您可以更改
Imagem
的映射,这将在
Imagem
之前保留Receita
我发现
PersistanceSpecification
有效对于相当直接的关系来说很好,但如果您有复杂的对象图,则必须对所有对象启用级联。不过,您的场景相当简单,因此这个小更改应该允许您使用 PersistanceSpecification 进行测试。编辑:
还要确保在您的
AdicionaImagem
函数中设置图像的父级。这是一个例子:You could change your mapping of
Imagem
This will persist
Receita
beforeImagem
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 usingPersistanceSpecification
.Edit:
Also make sure in your
AdicionaImagem
function you are setting the parent of the image. Here is an example:您的代码中可能存在两个问题。
自己已被禁用。这意味着没有为 Imagem 生成代理
实例和字节不能延迟加载:不可能完成的任务(至少现在在我看来,不确定)。
从数据库简单加载 (
session.Get(id);
) 会导致像这样的例外:
无效的转换(检查您的映射是否属性类型不匹配); Imagem 的设置者
。解决方案是在 Imagem 上启用延迟加载或在 Bytes 属性上禁用延迟加载。
另一个实例。这意味着默认的相等比较器不
工作顺利。您需要提供自己的相等比较器来解决
这个问题(查看更多详细信息)。
这是 Receita 和 Imagem 实体,实现 IEqualityComparer 和 PersistentSpecification 片段。此代码在 NH3.1 和 FNH 1.2 中运行良好。如果您的代码与这些代码片段有所不同,请告诉我。
There are two possible issues in your code.
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 toexceptions 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.
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.