Castle ActiveRecord中Inverse对Delete的影响

最近在项目中使用Castle ActiveRecord,在使用HasMany定义的关联时出现了无法级联删除的问题。
我在项目中定义了两个实体类FeedEntry和FeedEntryLink如下:

[ActiveRecord(Table = "FeedEntries")]
public class FeedEntry : ActiveRecordBase<FeedEntry>
{
[PrimaryKey(PrimaryKeyType.GuidComb)]
public Guid Id { get; set; }

[Property]
public string Title { get; set; }

[Property]
public string Content { get; set; }

[Property]
public DateTime LastUpdatedTime { get; set; }

[HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
public IList<FeedEntryLink> FeedEntryLinks { get; set; }
}


[ActiveRecord(Table = "FeedEntryLinks")]
public class FeedEntryLink : ActiveRecordBase<FeedEntryLink>
{
[PrimaryKey(PrimaryKeyType.GuidComb)]
public Guid Id { get; set; }

[Property]
public string RelationshipType { get; set; }

[Property]
public string MediaType { get; set; }

[Property]
public string Uri { get; set; }

[BelongsTo("FeedEntryId")]
public FeedEntry FeedEntry { get; set; }
}

其中FeedEntry中有一个集合属性FeedEntryLinks定义了它到类FeedEntryLink的一对多关联。而在FeedEntryLink中则有一个FeedEntry属性关联到父类FeedEntry。
在我的应用中需要删除所有的FeedEntry,因此我使用了下面的语句:

FeedEntry.DeleteAll();

看似非常简单的一个语句,执行的时候却报出了下面的错误:

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'FeedEntryId', table 'calendar-test.dbo.FeedEntryLinks'; column does not allow nulls. UPDATE fails.
The statement has been terminated.


明明是想删除,可是却试图往外键列中插入NULL,这是为什么呢?
不甘心的我打开sql server profiler,在执行语句FeedEntry.DeleteAll()时监控了生成的sql语句,果然发现出现了如下奇怪的sql:

exec sp_executesql N'UPDATE FeedEntryLinks SET FeedEntryId = null WHERE FeedEntryId = @p0',N'@p0 uniqueidentifier',@p0='7303FFBF-3E3C-4CB3-8ED5-9EF9016BFE0F'


看来真的是在试图插入空值!
经过查验多发资料,发现原来是Inverse惹的祸!
根据nhibernate的官方说明,Inverse属性指定了双向关联中的所有者,它的默认值为false。因此,在我的问题中,默认由关联的“子”方也就是FeedEntryLink来维护关联。
当我需要删除父表中的记录时,维护关联的子表方为了解除关联,就会试图把其所引用的父表设为空,然后再试图删除父表的记录,因此就有了上述生成的奇怪sql语句。
那么如果我把Inverse设置成true呢?比如说我把上面的HasMany改成:

[HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true)]
public IList<FeedEntryLink> FeedEntryLinks { get; set; }

这个时候再执行删除操作,会生成怎样的sql呢?再次使用sql server profiler我抓到了如下sql:

exec sp_executesql N'DELETE FROM FeedEntryLinks WHERE Id = @p0',N'@p0 uniqueidentifier',@p0='65EBBCF5-FBA7-4206-8C06-9EF90162559A'

这确实是我期望的删除命令。由于这时候由“父”方负责维护关联,因此当它试图删除父记录时,需要保证所有依赖关联的子记录都已被删除,所以就会执行上面的sql命令。


最后总结一下:Inverse定义了关联的维护方。
(1)当由子方来维护关联时,删除父记录时子记录会试图将关联断开,也就是置空。
(2)当由父方来维护关联时,删除父记录时会试图级联删除子记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值