2009-10-03 76 views
1

更新: 看来,将我的映射从Cascade.All()更改为Cascade.AllDeleteOrphan()修复了我的大部分问题。我仍然必须在OperatingState上明确地设置公司属性,这似乎是不必要的,因为它被添加到公司实体中,但至少我可以在更新期间使用它。我仍然需要用创建来测试。流利的NHibernate HasMany收集问题

如果任何人可以解释,那将是一个很大的帮助。

更新2:在玩了一些之后,似乎并不总是需要指定父实体。

原贴

我有2个相关的实体

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; } 
} 

而且他们这样映射:

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); 
     } 
} 

所以,一切都很好,直到我尝试用新的更新公司运行状态

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 

它弹了有:

无法插入NULL值插入 列 'CompanyID',表 'ConsumerCartel.dbo.CompanyOperatingState'; 列不允许有空值。 INSERT 失败。该声明已被终止 。

但是,如果我做2个改变它种工作

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 

将在另外添加新的状态,以旧的,这不是我想要的。但是,即使在明确设置公司(我将其添加到映射列表时,我不应该这样做)的情况下,也可以使用,但如果清除列表,则不起作用。

此代码已在其他实体上工作,但不在这一个,所以我认为这应该工作作为书面。我究竟做错了什么?

回答

2

您是否尝试过使用Inverse()?

HasMany(x => x.OperatingStates) 
    .Inverse() 
    .Cascade.All() 
    .Table("OperatingState"); 
+0

感谢您的回答。实际上,.Inverse是帮助我引入.AllDeleteOrphan()选项的原因。 – 2009-10-05 14:51:03