views:

530

answers:

1

Update: It appears that changing my mapping from Cascade.All() to Cascade.AllDeleteOrphan() fixes most of my issues. I still have to explicitly set the Company property on the OperatingState, which seems unnecessary as it's being added to the Company entity, but at least I can work with that during an update. I still need to test that with a create.

If any one can explain that, that would be a big help.

Update 2: After playing with it some more, it appears I don't always have to specify the parent entity.

Original Post

I have 2 related entities

public class Company {
        //... fields
        public virtual IList<OperatingState> OperatingStates { get; set; }
}

public class OperatingState {
        public virtual Company Company { get; set; }// Mapped on CompanyID
        public virtual string State { get; set; }
}

And they are mapped like this:

 public class CompanyMap : ClassMap<Company> {
        public CompanyMap() {
        //... fields 
          HasMany(x => x.OperatingStates)
                .Cascade.All()
                .Table("OperatingState");
        }
}
 public class OperatingStateMap : ClassMap<OperatingState> {
        public OperatingStateStateMap() {
            Id(x => x.ID);
            References(x => x.Company);
            Map(x => x.State);
        }
 }

So all is well until I try to update Company with new Operating States

Company company = _repo.GetSingle(123);
 company.OperatingStates.Clear();
 foreach(string state in form["OperatingStates"].Split(',')) {
    company.OperatingStates.Add(new OperatingState(state));
 }
 _repo.Save(company); // calls ISession.SaveOrUpdate

It bombs out with:

Cannot insert the value NULL into column 'CompanyID', table 'ConsumerCartel.dbo.CompanyOperatingState'; column does not allow nulls. INSERT fails. The statement has been terminated.

However, if I make 2 changes it kind of works

Company company = _repo.GetSingle(123);
 // don't clear the list this time;
 foreach(string state in form["OperatingStates"].Split(',')) {
    OperatingState os = new OperatingState(state);
    // explicitly setting the company
    os.Company = company;
    company.OperatingStates.Add(os);
 }
 _repo.Save(company); // calls ISession.SaveOrUpdate

Which will add the new states in addition to the old ones, which is not what I want. However, even when explicitly setting the company (which I shouldn't have to do when it's added to a mapped list?) it doesn't work if the list is cleared.

This code has worked on other entities, but not on this one, so I think this should work as written. What am I doing wrong?

+1  A: 

Have you tried using Inverse()?

HasMany(x => x.OperatingStates)
    .Inverse()
    .Cascade.All()
    .Table("OperatingState");
Per Erik Stendahl
Thanks for your answer. Actually, .Inverse was what helped lead me to the .AllDeleteOrphan() option.
cadmium