在Castle.ActiveRecord 实体类中,若是两个对象有 “多对多” 关系,通常的作法是将其分解为 两个“一对多”关系,但有时引起了 “您要删除 或 引用 的对象#2在数据库中不存在”的异常数据库
百思不得其解,一样的用法在“媒体引用”中一直都是正常的,为何在“专题引用” 和“ Web栏目引用” 中就出现异常呢?c#
经过遍历代码发现了细微的差异:缓存
在“媒体”的业务对象加载时,为了判断一个对象是否能够删除,常查询其被引用的 次数是多少,使用的方法是:DALMediaReference.FindCount(data) 性能
在“专题”的业务对象加载时,为了判断一个对象是否能够删除,常查询其被引用的 次数是多少,使用的方法是:data.SubjectReferences != null && data.SubjectReferences.Count > 0 spa
经过对比分析,“媒体”的检查使用是的 数据库 查询方法,最终会在数据中运行,而在“专题”中使用的是 “对象的引用” ,特别是在开启了数据加载缓存时,虽然数据库的引用已被删除,因为缓存存在的缘由,内存中的引用(专题引用)对象未从引用列表(data.SubjectReferences)中删除,因为引用它的对象没有及时的维护二者的关系(删除时从二者的引用 关系中 删除),所以在 使用 data.SubjectReferences 语句时会加载 已从数据库中删除的对象。code
缘由显然已经找到,解决的办法有以下:orm
if (data.WebCategories != null && data.WebCategories.Count > 0){ List<DALWebInformationCategory> tempWC = new List<DALWebInformationCategory>(data.WebCategories); foreach(var item in tempWC) { DALCategory _Category = item.Category; _Category.CategoryReferences.Remove(item); data.WebCategories.Remove(item); item.Delete(); } }
但也引入了另外的问题:对象
以上的解决方案 维护了缓存中的内存对象,经过ID取得对象时,没必要执行数据库IO,所以性能较好,但必须在全部使用 “媒体引用”、“专题引用”这样的主对象执行删除操做时, 必需要增长代码来维护这些关系,所以增长了工做量,对于象“媒体引用”这样的对象来讲,工程量至关浩大,而且也 形成了 代码侵入,使主对象过多的分心来处理这些逻辑,违反了 对象的 单一性原则。内存
经过 查询数据库 判断的方法,虽然在数据加载时都有一次数据库IO,带来了必定的性能损耗,但其 有效避免了上述缺点,所以仍是比较理想的选择。ci