涉及Association的更新,有时还会引发异常,我们来看下面这段代码:
1 var context = GenerateContext();
2 Publisher publisher = context.Publishers.Where(
3 p => p.PublisherID == new Guid("ae825c5f-465d-4eb5-a2bb-cc1aeb5edb7d")).Single();
4 var book = publisher.Books.First();
5 publisher.Books.Remove(book);
6
7 context.SubmitChanges();
这段代码的意图是删除Publisher对象相关的某Book对象,看起来是很漂亮的集合操作,但是运行时抛出异常:
“An attempt was made to remove a relationship between a Publisher and a Book. However, one of the relationship's foreign keys (Book.PublisherID) cannot be set to null.“
还记得我们在调用Publisher.Books.Add时候,EntitySet的会调用 attach_Books来修改Book.PublisherID吗?在调用Publisher.Books.Remove的时候,EntitySet会调用detach_Books来让Book.PublisherID = default(Guid)
而对于LINQ2SQL,只跟踪到了Book.PublisherID属性发生了更改,所以在调用 SubmitChanges会尝试更新Book记录而产生上述外键异常。解决这个问题的方法是:在Book.PublisherID的 ColumnAttribute定义中,把DeleteOnNull设为true。这样当Context发现Book.PublisherID为空(default(Guid)相当于Guid.Empty)时,不是执行Update而是Delete操作。
删除
根据msdn,目前版本的LINQ是不支持级联删除的,需要级联删除只能依赖数据库的级联删除,否则也可以考虑下面的方式:
1 context.Books.DeleteAllOnSubmit(publisher.Books.AsEnumerable());
2 context.Publishers.DeleteOnSubmit(publisher);
3 context.SubmitChanges();
你不需要担心事务的问题,context.SubmitChanges在执行时会自动创建本地数据库事务,来保证操作的完整。关于事务的问题,我们在“LINQ那些事(3)”中会有详细讨论。
查询