I have 3 classes and their mappings and each of them has reference to the previous like:
A -> B -> C
A can have C but only if B got C(due to its impossible A -> C)
class A
{
public virtual int Id {get;set;}
public virtual string messageA {get;set;}
public virtual IList<B> Bs {get;set;}
}
class B
{
public virtual int Id {get;set;}
public virtual string messageB {get;set;}
public virtual A A {get; set;}
public virtual IList<C> Cs {get;set;}
}
class C
{
public virtual int Id {get;set;}
public virtual string messageC {get;set;}
public virtual B B{get;set;}
}
//Mappings
class AMap : ClassMap<A>
{
public AMap()
{
Id(x => x.Id);
Map(x => x.messageA);
HasMany(x => x.Bs);
}
}
class BMap : ClassMap<B>
{
public BMap()
{
Id(x => x.Id);
Map(x => x.messageB);
References(x => x.A).Cascade.All();
HasMany(x => x.Cs);
}
}
class CMap : ClassMap<C>
{
public CMap()
{
Id(x => x.Id);
Map(x => x.messageC);
References(x => x.B).Cascade.All();
}
}
I got such an error while trying to commit:
object references an unsaved transient instance - save the transient instance before flushing or set cascade action for the property to something that would make it autosave. Type: NHibernateTest.C, Entity: NHibernateTest.C.
I was looking for the solution, someone said I have to modify foreign key update rule into cascade, I did it and still not working.
I just want to mention that it was working with A -> B relation, when I added C the error occured.
To avoid such problems in future you should make sure that:
The following test case works as you expect (A->B->C).
Model definitions:
public class A
{
public virtual int Id { get; set; }
public virtual string messageA { get; set; }
public virtual IList<B> Bs { get; set; }
}
public class B
{
public virtual int Id { get; set; }
public virtual string messageB { get; set; }
public virtual IList<C> Cs { get; set; }
}
public class C
{
public virtual int Id { get; set; }
public virtual string messageC { get; set; }
}
Map definitions:
public class AMap : ClassMap<A>
{
public AMap()
{
Table("A");
Id(x => x.Id).Column("Id");
Map(x => x.messageA);
HasMany(x => x.Bs).Cascade.All();
}
}
public class BMap : ClassMap<B>
{
public BMap()
{
Table("B");
Id(x => x.Id).Column("Id"); ;
Map(x => x.messageB);
HasMany(x => x.Cs).Cascade.All();
}
}
public class CMap : ClassMap<C>
{
public CMap()
{
Table("C");
Id(x => x.Id).Column("Id"); ;
Map(x => x.messageC);
}
}
NUnit test method:
[Test]
public void ShouldCorrectlyMapA()
{
var objectA = new A
{
Id = 1,
messageA = "Message A",
Bs = new List<B> {
new B
{
messageB = "Message B",
Cs = new List<C>
{
new C
{
messageC = "Message C"
}
}
}
}
};
new PersistenceSpecification<A>(_session)
.VerifyTheMappings(objectA);
}
Using in-memory SQLite unit test, the test runners output of
Schema creation:
create table A ( Id integer primary key autoincrement, messageA TEXT ) create table B ( Id integer primary key autoincrement, messageB TEXT, A_id INT, constraint FKCDCAB7DE9EFDCD1D foreign key (A_id) references A ) create table C ( Id integer primary key autoincrement, messageC TEXT, B_id INT, constraint FKCDCAB7DD3844B1E1 foreign key (B_id) references B )
DML operations on the just created schema:
NHibernate: INSERT INTO A (messageA) VALUES (@p0); select last_insert_rowid();@p0 = 'Message A' [Type: String (0)] NHibernate: INSERT INTO B (messageB) VALUES (@p0); select last_insert_rowid();@p0 = 'Message B' [Type: String (0)] NHibernate: INSERT INTO C (messageC) VALUES (@p0); select last_insert_rowid();@p0 = 'Message C' [Type: String (0)] NHibernate: UPDATE B SET A_id = @p0 WHERE Id = @p1;@p0 = 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)] NHibernate: UPDATE C SET B_id = @p0 WHERE Id = @p1;@p0 = 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.