NHibernate - Unable to save child entities

2019-08-15 04:26发布

问题:

This is supposed to be a simple 1-N relationship, however I am not able to save the children as NHibernate uses null as a value in the insert statement of the child.

 public class Event
 {
  public virtual string Id { get; set; }
  public virtual string Name { get; set; }        
  public virtual IList<EventParameter> Parameters{ get; set; }

  public Event() { Parameters = new List<EventParameter>(); }
 }

[Serializable]
public class EventParameter : Parameter
{
  public virtual Event Event { get; set; }
  public virtual string ComparisonMethod { get; set; }
  public override bool Equals(object obj) {}
  public override int GetHashCode() {}
}

The mappings are like this

public EventMapping()
{
    Table(...);

    Id(x => x.Id)
        .Column(...)
        .GeneratedBy
        .Custom<global::NHibernate.Id.SequenceGenerator>(builder => builder.AddParam("sequence", "...")); 

    Map(x => x.Name).Column("Name").Length(100);

    HasMany<EventParameter>(x => x.Parameters)
            .KeyColumns.Add(...)
            .Inverse()
            .Cascade.All();
}

public EventParameterMapping()
{
    Table(....);

    CompositeId()
        .KeyProperty(x => x.Event.Id, "...")
        .KeyProperty(x => x.ParameterId, "..."); 

    References(x => x.Event);          
}

The Insert statement for the parent is correct, however for the child it is not.

INSERT INTO ...
        (...columns...)
VALUES  (..., null, ...)

Before this happens I get the following warning: Unable to determine if entity is transient or detached; querying the database. Use explicit Save() or Update() in session to prevent this.

I do use Save() in the transaction. Any ideas why this happens?

回答1:

Solution here is suprisingly simply. We have to use inverse="true" mapping:

HasMany<EventParameter>(x => x.Children)
        .KeyColumns.Add("...")
        .Inverse()
        .Cascade.All();

But, this is kind of optimization, which would require both sides of relation to be always properly set in our C# code:

var parent = ...;
var child = new Child();
// both sides MUST be set
parent.Children.Add(child);
child.Parent = parent;

Please, observe this for more details

Inverse = “true” example and explanation