Nhibernate 持久性规范与逆
很久以前,我已经在Fluent NH小组中发布了这篇文章,但直到今天才得到任何答案。所以,问题是:我定义了一对多关系,并且一侧设置了反向标志。映射代码如下所示:Nhibernate 持久性规范与逆,nhibernate,collections,fluent-nhibernate,inverse,Nhibernate,Collections,Fluent Nhibernate,Inverse,很久以前,我已经在Fluent NH小组中发布了这篇文章,但直到今天才得到任何答案。所以,问题是:我定义了一对多关系,并且一侧设置了反向标志。映射代码如下所示: public class MapeamentoReceita : ClassMap<Receita> { public MapeamentoReceita() { Table("Receitas"); Not.LazyLoad(); Id(rec => rec.
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();
}
}
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();
}
}
public类映射eamentoreceita:ClassMap{
公共地图{
表(“收据”);
不是。懒汉();
Id(记录=>记录Id,“IdReceita”)
.产生于
.HiLo(“TabelaHilo”、“ProximoHi”、“1000”、“Tabela='receitas'))
.违约(0);
版本(rec=>rec.Versao);
//其他道具在这里
HasMany(rec=>rec.Imagens)
.Access.CamelCaseField((前缀.下划线))
.AsBag()
.Cascade.All()
.KeyColumn(“IdReceita”)
.Not.LazyLoad()
.Inverse();
}
}
现在,Imagem的映射如下所示:
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();
}
}
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();
}
}
公共类映射eamentoimagem:ClassMap{
公共MapeamentoImagem(){
表(“图像”);
不是。懒汉();
Id(img=>img.Id,“IdImagem”)
.产生于
.HiLo(“TabelaHiLo”、“ProximoHi”、“1000”、“Tabela='imagens'))
.违约(0);
映射(img=>img.Bytes)
.CustomSqlType(“图像”)
.CustomType()
.LazyLoad()
.长度(2000000000)
.Not.Nullable()
.Not.Update();
参考(img=>img.Receita)
.栏(“IdReceita”)
.Cascade.None();
}
}
下面是测试这些类持久性的代码:
new PersistenceSpecification<Receita>(sess)
.CheckList(rec => rec.Imagens,
_imagens,
(receita, imagem) => receita.AdicionaImagem(imagem))
.VerifyTheMappings();
新的PersistenceSpecification(sess)
.检查表(记录=>记录图像,
_imagens,
(receita,imagem)=>receita.AdicionaImagem(imagem))
.验证应用程序();
即使Inverse处于“打开”状态,PersistenceSpecification也会在插入Receita之前尝试插入Imagem。由于IdReceita是配置为不接受null的外键,因此我最终遇到了一个异常。我尝试过编写使用receita的“真实世界代码”,它可以正常工作(我打开了SQL,我可以看到在这种情况下,receita应该插入到Imagem之前)
由于FH group上没有人回答这个问题,我想知道是否有人可以确认PersistenceSpecification行为是一个bug
谢谢。试试:
References(img => img.Receita)
.Column("IdReceita")
.Not.Nullable();
我的猜测是,您的真实世界代码首先保存Recieta,以便以正确的顺序发布插入。如果您先更改该代码以保存Imagem,您将得到相同的错误,因为NHibernate将尝试插入Imagem,然后使用外键更新它。您可以更改
Imagem的映射。
References(img => img.Receita)
.Column("IdReceita")
.Cascade.SaveUpdate();
这将在Imagem
References(img => img.Receita)
.Column("IdReceita")
.Cascade.SaveUpdate();
我发现,PersistanceSpecification
适用于相当直接的关系,但如果您有复杂的对象图,则必须在所有对象上启用级联。不过,您的场景相当简单,因此这一小小的更改应该允许您使用persistencespecification
对其进行测试
编辑:
还要确保在AdicionaImagem
功能中设置了图像的父级。以下是一个例子:
public virtual void AdicionaImagem(Imagem newImagem)
{
newImagem.Receita = this;
imagems.Add(newImagem);
}
你这样试过吗
var receita = BuildMeAReceita();
var imagems = BuildSomeImagems();
foreach(var imagem in imagems){
receita.AdicionaImagem(imagem);
}
new PersistenceSpecification<Receita>(sess)
.VerifyTheMappings(receita);
var receita=BuildMeAReceita();
var imagems=BuildSomeImagems();
foreach(imagems中的var imagem){
AdicionaImagem(imagem);
}
新PersistenceSpecification(sess)
.验证申请(收据);
您的代码中可能存在两个问题
session.Get(id);
)简单加载会导致
例外情况如下:
无效强制转换(检查映射是否存在属性类型不匹配);照排机。
解决方案是在Imagem上启用延迟加载,或在字节属性上禁用延迟加载
下面是和实体、和代码段的实现。该代码在NH3.1和FNH1.2中运行良好。请告诉我您的代码是否与这些代码片段有所不同。你好,杰米。尝试了它,但它不起作用(最终使用非null属性引用null或瞬时值Receita)。这是否意味着PersistenceSpecification不是测试映射的好方法???您可以发布测试中填充
\u imagens
字段的代码吗?还有Receita.AdicionalImagem(Imagem)
?谢谢,你好,科尔。完成了,但它仍然在插入Receita之前插入imagem。我相信问题在于PersistenceSpecification运行插入的方式(因为我启用了SQL跟踪,很容易看出在我的应用程序中使用它最终会做正确的事情,即在每个Imagem实例之前插入Receita)。您使用的是哪种版本的Fluent NH?如果您将映射更改为上述内容并尝试保存Imagen
对象(在PersistanceSpecification之外),它是否会创建Receita
<代码>会话.保存(testImagen)同样在您的AdicionaImagem
函数中,您是否在此处设置父引用?请看我的编辑为例。你好,科尔。是的,当我打开一个事务并保存一个Receita时,它将首先插入Receita,然后才插入Imagem实例。哦,是的,我正在这样做:public void AdicionaImagem(Imagem Imagem){Contract.Requires(Imagem!=null);Contract.Requires(image