NHibernate 升级至5.2版本后多对多关联过滤器失效问题
我看了你升级NHibernate从5.1.7到5.2.0时遇到的多对多关联过滤器失效问题,结合你贴的代码,咱们来捋捋原因和解决思路:
问题现象回顾
在旧版本(5.1.7及以下)中,用session.Get<Webcam>(123241)获取实体后,webcamByGet.Supplies.Count返回0——这符合预期,因为你给Webcam和Supply都设置了DeletedAt值,过滤器本该把这些已标记删除的关联项过滤掉。但升级到5.2.0+后,这个计数不为0,说明多对多关联上的过滤器没生效。
可能的原因
NHibernate 5.2版本对多对多关联的过滤器处理逻辑做了调整,尤其是延迟加载集合的初始化阶段,之前的ApplyChildFilter方法可能不再正确把过滤条件传递到集合加载的SQL查询里,导致过滤器没起作用。
解决办法
试试下面这几个调整方案:
替换
ApplyChildFilter为ApplyFilter
在你的多对多映射配置里,把ApplyChildFilter<DeletedAtIsNullFilterConvention.NotDeletedFilter>()替换成ApplyFilter<DeletedAtIsNullFilterConvention.NotDeletedFilter>()。比如修改WebcamMap里的关联配置:HasManyToMany(x => x.Supplies) .Schema("mod_list_management") .Table("DynSuppliesWebcams") .ParentKeyColumn("WebcamId") .ChildKeyColumn("SupplyId") .ApplyFilter<DeletedAtIsNullFilterConvention.NotDeletedFilter>() // 替换原ApplyChildFilter .Cascade.All();同样的,
SupplyMap里的多对多关联也做相同替换。确认过滤器的注册和启用时机
你已经在代码里调用了session.EnableFilter(DeletedAtIsNullFilterConvention.NotDeletedFilter.FilterName),但要确保这行代码是在加载集合之前执行的。另外检查CreateSessionFactory里是否正确注册了过滤器:Add(typeof(DeletedAtIsNullFilterConvention.NotDeletedFilter))这一步没问题,但可以确认下过滤器的定义是否正确,比如过滤条件是不是DeletedAt IS NULL(对应你设置的DeletedAt = DateTime.UtcNow,应该被过滤)。调试生成的SQL语句
你已经开启了ShowSql(),运行代码时仔细看加载Supplies集合的SQL语句,有没有包含DeletedAt IS NULL的过滤条件。如果没有,说明过滤器确实没被应用到集合查询中,这时候要重点检查映射配置里的过滤器应用方式。显式初始化集合
因为你的集合是延迟加载的,5.2版本中延迟加载的初始化逻辑可能有变化,可以尝试显式初始化集合后再检查计数:var webcamByGet = session.Get<Webcam>(123241); NHibernate.NHibernateUtil.Initialize(webcamByGet.Supplies); // 显式初始化 var count2 = webcamByGet.Supplies.Count;
验证
修改配置后重新运行测试代码,观察count2是否回到预期的0,同时看生成的SQL是否包含过滤条件,确认过滤器生效。
备注:内容来源于stack exchange,提问作者Sahin

