使用
.NET Core SDK(反映任何global.json): 版本:2.2.300 提交:73efd5bd87
和
Nhibernate 5.2.5
具有以下实体
public class Customer : Entity {
public Customer() {
Initialize();
}
public virtual string Name { get; set; }
public virtual string LegalName { get; set; }
public virtual string VATCode { get; set; }
public virtual ICollection<Site> Sites { get; set; }
public virtual DateTime Created { get; set; } = DateTime.UtcNow;
private void Initialize() {
Sites = new List<Site>();
}
}
public class Site : Entity {
public virtual string Address { get; set; }
public virtual string City { get; set; }
public virtual string Country { get; set; }
public virtual Customer Customer { get; set; }
}
使用以下映射器
internal class CustomerConfiguration : ClassMapping<Customer> {
public CustomerConfiguration() {
Table( TableNames.CustomersTable );
Id( x => x.EntityID, im => {
im.Column( "CustomerID" );
im.Generator( Generators.Identity );
} );
[... code omitted for brevity ...]
Set<Site>( property => property.Sites,
collection => {
collection.Fetch( CollectionFetchMode.Join );
collection.Lazy( CollectionLazy.Lazy );
collection.Cascade( Cascade.Persist.Include( Cascade.DeleteOrphans ) );
collection.Inverse( true );
collection.Key( keyMapping => {
keyMapping.Column( "CustomerID" );
} );
},
mapping => {
mapping.OneToMany( relationalMapping => {
relationalMapping.Class( typeof( Site ) );
} );
} );
}
}
internal class SiteConfiguration : ClassMapping<Site> {
public SiteConfiguration() {
Table( TableNames.SitesTable );
Id( x => x.EntityID, im => {
im.Column( "SiteID" );
im.Generator( Generators.Identity );
} );
[... code omitted for brevity ...]
ManyToOne( x => x.Customer, mm => {
mm.Column( "CustomerID" );
mm.NotNullable( true );
} );
}
}
我想这个映射是不正确的,因为如果我做类似的事情
using ( var session = sessionFactory.OpenSession() ) {
var customer = new Customer() {
Name = $"Customer 1",
LegalName = $"Customer 1 LLC",
VATCode = "xxxxxxxxx",
Created = DateTime.UtcNow
};
customer.Sites.Add( new Site() {
Address = $"Address Customer 1",
City = $"City Customer 1",
Country = $"Country Customer 1",
Customer = customer
} );
session.Save( customer );
}
我收到以下异常
未处理的异常:NHibernate.TransientObjectException:对象引用了一个未保存的瞬态实例-在刷新之前保存该瞬态实例,或者将该属性的级联操作设置为可以使其自动保存的内容。类型:Nhibernate.ConsoleApp.Entities.Site,实体:[Site 0]
有什么建议吗?
编辑
实际上,问题出在另一个区域。这是因为存在两个注册的侦听器(IDeleteEventListener
和IUpdateEventListener
)。每当我添加这些更新和删除均不起作用。但是,由于Roman Artiukhin评论
答案 0 :(得分:2)
例外情况是telling,其中根实体Customer
持有对其他(Site
)实体的引用,该实体是临时实体。因此,根实体无法保留。
方案1:未配置任何级联选项。
在这种情况下,必须先保存子对象或引用的对象。
using ( var session = sessionFactory.OpenSession() ) {
var customer = new Customer() {
Name = $"Customer 1",
LegalName = $"Customer 1 LLC",
VATCode = "xxxxxxxxx",
Created = DateTime.UtcNow
};
Site site = new Site() {
Address = $"Address Customer 1",
City = $"City Customer 1",
Country = $"Country Customer 1",
Customer = customer
}
customer.Sites.Add(site);
session.Save( customer );//<--Save the master
session.Save( site );//<--Save the site
...
...
...
session.Flush();//<--You are calling this somewhere in your code
}
这应该有效。
方案2:未为所有INPUT配置级联选项。 UPDATE或DELETE操作。
在这种情况下,必须更改配置,或者必须先保存子对象或引用的对象。
您已经:
collection.Inverse( true );
Include
为DeleteOrphans | Persist
添加了两个Cascade
值。所以这不是问题。
场景3:相关的临时对象已实例化并与持久对象相关联,但不对这些对象执行保存操作。
在这种情况下,必须通过以下命令将训练对象与当前会话分离:ISession.Evict(obj)
您可以调用Evict
代替Save
来显式附加那些对象,如上所述。
要了解更多信息,请查看documentation,其中介绍了各种策略。
答案 1 :(得分:1)
我的猜测是收藏不是您的问题。看来您在其他地方暴露了Site
实体(例如多对一customer.LastSite
属性或类似内容)。并且在保存集合之前,级联逻辑偶然发现了这个尚未保存的Site
属性。因此,您必须确保其他Site
属性也具有Cascade.Persist
映射