Ich habe ein Problem damit, was ein ziemlich einfacher (ich würde denken) NHibernate-Anwendungsfall sein.NHibernate legt den Fremdschlüssel in der sekundären Aktualisierung und nicht in der ursprünglichen Einfügung fest. Nicht-Null-Einschränkung in der Schlüsselspalte
Ich habe einen klassischen Elternteil und ein Kind Entität wie folgt:
public class Parent
{
public virtual int ParentId { get; set; }
public virtual string Name { get; set; }
public virtual IList<Child> Children { get; set; }
}
public class Child
{
public virtual int ChildId { get; set; }
public virtual Parent Parent { get; set; }
public virtual string Name { get; set; }
}
und Zuordnungen wie folge:
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Id(x => x.ParentId).GeneratedBy.Native();
Map(x => x.Name);
HasMany(x => x.Children).KeyColumn("ParentId").Cascade.SaveUpdate();
}
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
Id(x => x.ChildId).GeneratedBy.Native();
Map(x => x.Name);
References(x => x.Parent).Column("ParentId").ReadOnly().Not.Nullable();
}
}
Schließlich Ich habe einen einfachen Tests:
[Test]
public void Test_save_family()
{
var parent = new Parent();
var child = new Child {Parent = parent};
parent.Children = new List<Child>{child};
SessionManager.WithSession(
session =>
{
session.Save(parent);
session.Flush();
});
}
Der Test schlägt mit einer System.Data.SqlClient.SqlException fehl: Der Wert NULL kann nicht in die Spalte 'ParentId' eingefügt werden. Das ist richtig, da die Spalte nicht nullfähig ist, aber warum fügt sie null ein?
Wenn ich die NULL-Constraint entfernen, speichern die funktioniert, weil NHibernate zuerst die Eltern einfügt, dann das Kind einfügt, aktualisiert dann die ParentId Spalte auf dem untergeordneten Datensatz, wie in dieser Ausgabe gezeigt:
NHibernate: INSERT INTO [Parent] (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = NULL
NHibernate: INSERT INTO [Child] (Name) VALUES (@p0); select SCOPE_IDENTITY();@p0 = NULL
NHibernate: UPDATE [Child] SET ParentId = @p0 WHERE ChildId = @p1;@p0 = 2, @p1 = 1
Dies scheint bizarr für mich, da in fast allen Fällen Fremdschlüsselspalten dieser Art als nicht nullbar deklariert werden und daher der Fremdschlüssel beim Einfügen bereitgestellt werden muss. Warum setzt NHibernate den Fremdschlüssel nicht beim ersten Einfügen der untergeordneten Zeile und wie behebe ich das?
James, okay Entfernen der ReadOnly() Qualifier funktionierte, um den Test zu erhalten. Jetzt bin ich jedoch verwirrt über die Bedeutung von ReadOnly(). Mein Verständnis war, dass ReadOnly() bedeutet, dass NHibernate die Spalte nach der ursprünglichen Einfügung nie aktualisieren wird, nicht dass es niemals einen Wert bei der Einfügung zuweisen wird. –
ReadOnly() bedeutet, dass der Wert niemals beim Einfügen oder Aktualisieren geschrieben wird. Es wird hauptsächlich für Nachschlagetabellen und berechnete Spalten verwendet. –
Hmm, das wusste ich jetzt, wo du es erwähnst. Ich glaube, ich habe ReadOnly() als Eigenschaft Attribut mit ReadOnly als Entity-Attribut verwechselt. Muss alt werden. :) Danke für die Hilfe! –