dotnetcore / sharding-core

high performance lightweight solution for efcore sharding table and sharding database support read-write-separation .一款ef-core下高性能、轻量级针对分表分库读写分离的解决方案,具有零依赖、零学习成本、零业务代码入侵
https://xuejmnet.github.io/sharding-core-doc/
Apache License 2.0
1.17k stars 171 forks source link

ABP VNext内置过滤ShouldFilterEntity=>CreateFilterExpression查询报错Object reference not set to an instance of an object. #270

Open MrShenf opened 4 months ago

MrShenf commented 4 months ago

image image image

xuejmnet commented 4 months ago

@MrShenf

image

是否可以发一下的dbcontext是如何构建的是否没有吧LazyServiceProvider进行赋值

xuejmnet commented 4 months ago

你的抽象dbcontext是否是参考sharding-core源码的

image
MrShenf commented 4 months ago

使用的https://github.com/xuejmnet/ShardingWithFramework 这个Demo测试的

MrShenf commented 4 months ago

image

MrShenf commented 4 months ago

image

MrShenf commented 4 months ago

protected override bool ShouldFilterEntity(IMutableEntityType entityType) where TEntity : class { if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))) { return true; }

  return false;

}

protected override Expression<Func<TEntity, bool>> CreateFilterExpression() where TEntity : class { Expression<Func<TEntity, bool>> expression = null; if (base.LazyServiceProvider == null) { var lazyServiceProvider = GlobalContext.ServiceProvider.GetRequiredService(); base.LazyServiceProvider = lazyServiceProvider; } if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))) { if (IsMultiTenantFilterEnabled) { Expression<Func<TEntity, bool>> multiTenantFilter = e => EF.Property(e, "TenantId") == CurrentTenantId; expression = expression == null ? multiTenantFilter : CombineExpressions(expression, multiTenantFilter); } }

  return expression;

}

xuejmnet commented 4 months ago

EFCore的ServiceProvider是scope类型的你把app.serviceProvider给了一个静态变量他是全局单例的serviceprovider怎么能给abpcontext的LazyServiceprovider呢这样肯定是有问题呀

MrShenf commented 4 months ago

Update-Database 映射 数据库的时候就会报null值错误 image

xuejmnet commented 4 months ago

两者的生命周期都不一样

xuejmnet commented 4 months ago

你这玩意写的就有问题 CreateFilterExpression当然不可以这么处理了你依赖注入的生命周期弄错了不可以吧scope的服务提供者给静态属性的

MrShenf commented 4 months ago

那这个要怎么处理呢 那个是abp内置的 我只是测试重现这个问题

xuejmnet commented 4 months ago

这个是abp的我不是很清楚

MrShenf commented 4 months ago

AbpDbContext这个类里面自带的 image

xuejmnet commented 4 months ago

你看一下AbstractShardingAbpDbContex的LazyServiceProvider

image

打断点看看

MrShenf commented 4 months ago

这里是正常的可以获取到的 image

xuejmnet commented 4 months ago

这里是正常的可以获取到的 image

我看了代码确定是这样的吗

MrShenf commented 4 months ago

那两个方法我测试报错override了 其他没动 image

MrShenf commented 4 months ago

原因应该是 AbstractShardingAbpDbContext 继承AbpDbContext CreateFilterExpression是程序启动就会执行注册 此时 LazyServiceProvider为空导致 查询的时候获取public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService(); 这个报错了, 我使用的项目ABP.VNet 不是官网直接生成自带用户表的, 直接引用AbpDbContext没问题 我引用源码再调试一下 感谢作者耐心解答回复

xuejmnet commented 4 months ago

@MrShenf 主要是我没有你运行的代码也不是很清楚abp我本身不使用abp所以可能并不能对您发送的问题有太好的建议提供,不过附加一下调试源码应该可以了解更详细的信息(#^.^#)

MrShenf commented 4 months ago

这个项目里面有两个版本,main里面的AbstractShardingAbpDbContext写法和le7.x里面的写法不一样,使用main里面可以base.LazyServiceProvider有值 image image

MrShenf commented 4 months ago

是这个配置造成的,麻烦请教一下,这个配置可以去掉吗 image

xuejmnet commented 4 months ago

@MrShenf 使用main分支的而不是le7的,le7是sharding-core版本号小于7的时候的案例

xuejmnet commented 4 months ago

是这个配置造成的,麻烦请教一下,这个配置可以去掉吗 image

这个配置不可以去掉去掉会有问题,原则上来讲不会是这个配置的问题才对

xuejmnet commented 4 months ago

如果把这个配置去掉那么abp就没办法实现分表分库了

MrShenf commented 4 months ago

您写的实例项目我测试了一下,注释掉 override AbpDbContext那两个方法 base.LazyServiceProvider确实有值了image

MrShenf commented 4 months ago

使用这个配置可以吗 这样base.LazyServiceProvider有值 image