我目前的情况是文章每个只有1个结果。每篇文章可能有也可能没有结果。
理论上,这是一对一的映射,但由于NHibernate并不真正支持一对一,我使用一对多来代替。子表上的主键实际上是 ArticleID (FK)。
所以我有以下设置:
public class Article
{
public virtual Int32 ID { get;set;}
private ICollection<ArticleOutcome> _Outcomes {get;set;}
public virtual ArticleOutcome Outcome
{
get {
if( this._Outcomes !=null && this._Outcomes.Count > 0 )
return this._Outcomes.First();
return null;
}
set {
if( value == null ) {
if( this._Outcomes !=null && this._Outcomes.Count > 0 )
this._Outcomes.Clear();
}
else {
if( this._Outcomes == null )
this._Outcomes = new HashSet<ArticleOutcome>();
else if ( this._Outcomes.Count >= 1 )
this._Outcomes.Clear();
this._Outcomes.Add( value );
}
}
}
}
public class ArticleOutcome
{
public virtual Int32 ID { get;set; }
public virtual Article ParentArticle { get;set;}
}
public class ArticleMap : ClassMap<Article>
{
public ArticleMap() {
this.Id( x=> x.ID ).GeneratedBy.Identity();
this.HasMany<ArticleOutcome>( Reveal.Property<Article>("_Outcomes") )
.AsSet().KeyColumn("ArticleID")
.Cascade.AllDeleteOrphan() //Cascade.All() doesn't work too.
.LazyLoad()
.Fetch.Select();
}
}
public class ArticleOutcomeMap : ClassMap<ArticleOutcome>
{
public ArticleOutcomeMap(){
this.Id( x=> x.ID, "ArticleID").GeneratedBy.Foreign("ParentArticle");
this.HasOne( x=> x.ParentArticle ).Constrained ();
//This do not work also.
//this.References( x=> x.ParentArticle, "ArticleID" ).Not.Nullable();
}
}
现在我的问题是:
当我对结果进行插入/更新时,它会起作用。 e.g。
var article = new Article();
article.Outcome = new ArticleOutcome { xxx = "something" };
session.Save( article );
但是,在尝试通过文章本身删除时遇到SQL错误。
var article = session.Get( 123 );
session.Delete( article ); //throws SQL error.
错误是无法在ArticleOutcome表中的ArticleID中插入NULL 。
如果我将 Inverse()放置在文章的HasMany()映射中,则删除有效,但插入将失败。
有人有解决方案吗?或者我真的必须在ArticleOutcome表中添加代理键吗?
如果有人感兴趣的话,这是Fluent的映射。
public class ArticleMap : ClassMap<Article>
{
public ArticleMap() {
this.Id( x=> x.ID ).GeneratedBy.Identity();
this.HasOne( x=> x.Outcome ).Cascade.All();
}
}
public class Article
{
//... other properties
public virtual ArticleOutcome Outcome { get;set;}
}
答案 0 :(得分:0)
NHibernate确实支持一对一。
我有一个与你非常相似的案例。以下是相关部分:
class Articule
{
public virtual ArticleOutcome Outcome { get; set; }
}
class ArticuleOutcome
{
public virtual Article ParentArticle { get; set; }
}
映射(抱歉,我不使用Fluent,但翻译起来不难):
<class name="Article">
<id name="ID">
<generator class="identity"/>
</id>
<one-to-one name="Outcome" cascade="all"/>
</class/>
<class name="ArticleOutcome">
<id name="ID" column="ArticleId">
<generator class="foreign">
<param name="property">ParentArticle</param>
</generator>
</id>
<one-to-one name="ParentArticle" constrained="true"/>
</class/>
用法:
var article = new Article();
article.Outcome = new ArticleOutcome
{
xxx = "something",
ParentArticle = article
};
session.Save(article);
删除应该可以正常使用。