我在.net Core和.net框架中测试了NHibernate,请求null引用似乎是经过管理的,不会引发null引用,例如,当Property_a为null时,通过检索:x.Property_a.Property_B。
在另一个具有不同配置的项目上,这种情况是不受管理的,如果Property_a为null,我会得到一个null引用异常。nhibernate的版本是相同的,配置是如此巨大,以至于我找不到是什么解释了这种差异。
你知道哪种配置可能是造成这种差异的原因吗?
配置代码概述(我不能把所有东西都放进去,因为它太大了,但它是主要的东西(:
private static ISessionFactory InitializeSessionFactory<T>(bool isAglRebuild = false) where T : ICurrentSessionContext
{
try
{
_configuration = CreateConfiguration();
FluentConfiguration nhConfig = Fluently.Configure(_configuration)
.Mappings(m => System.AppDomain.CurrentDomain.GetAssemblies().ToList().ForEach(asm => {
m.FluentMappings.AddFromAssembly(asm);
}
));
if (SoNGSettings.isSecondLevelCachingEnabled)
{
nhConfig = nhConfig.Cache(x =>
{
switch (SoNGSettings.CacheManagerName)
{
default:
x.UseSecondLevelCache().ProviderClass<NHCaches.SysCache2.SysCacheProvider>()
.UseQueryCache();
break;
}
});
if (SoNGSettings.CacheManagerName == Consts.Caching.RedisManager)
{
nhConfig.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.CacheDefaultExpiration, "900"));
nhConfig.ExposeConfiguration(cfg => cfg.SetProperty("cache.use_sliding_expiration", Boolean.TrueString));
nhConfig.ExposeConfiguration(cfg => cfg.SetProperty("cache.configuration", SoNGSettings.CacheManagerServerName));
}
}
else
{
nhConfig = nhConfig.Cache(x => x.Not.UseSecondLevelCache());
}
string version = "";
if (AppReflection.GetFormBuilderAssembly() != null)
version = AppReflection.GetFormBuilderAssembly().GetName().Version.ToString();
var tmpSessionFactory = nhConfig
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.Isolation, "ReadCommitted"))
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.FormatSql, Boolean.TrueString)) //Format the SQL before sending it to the database and Format SQL Queries in Exported Files
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.GenerateStatistics, (SoNGSettings.isNHibernateProfiler ? Boolean.TrueString : Boolean.FalseString))) // Produce statistics on the number of queries issued, entities obtained, etc
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.Hbm2ddlKeyWords, Hbm2DDLKeyWords.None.ToString())) // Should NHibernate automatically quote all table and column names (ex: [TableName])
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.PrepareSql, Boolean.TrueString))
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.PropertyBytecodeProvider, "lcg")) // What bytecode provider to use for the generation of code (in this case, Lightweight Code Generator)
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.QueryStartupChecking, Boolean.FalseString))// Check all named queries present in the configuration at startup? (none in this example)
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.ShowSql, Boolean.FalseString)) // Show the produced SQL
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.StatementFetchSize, "100")) // The fetch size for resultsets
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.UseProxyValidator, Boolean.FalseString)) // Validate that mapped entities can be used as proxies
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.PropertyUseReflectionOptimizer, Boolean.TrueString))
//.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.CacheRegionPrefix, AppReflection.GetFormBuilderAssembly().GetName().Version.ToString()))
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.SessionFactoryName, version))
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.UseSqlComments, Boolean.FalseString)) // Enable the possibility to add SQL comments
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.UseQueryCache, Boolean.TrueString)) // Allows the results of a query to be stored in memory
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.WrapResultSets, Boolean.TrueString)) // Caches internally the position of each column in a resultset
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.BatchSize, "500"))
.ExposeConfiguration(cfg => cfg.SetProperty(NHCfg.Environment.CommandTimeout, SoNGSettings.DbCommandTimeout.ToString()))
.ExposeConfiguration(cfg => cfg.SetInterceptor(new ContextInterceptor()));
ISessionFactory sessionFactory = null;
if (isAglRebuild)
{
TypeFactory.ClearCustomRegistrations();
sessionFactory = tmpSessionFactory
.CurrentSessionContext<T>()
.BuildConfiguration()
.BuildSessionFactory();
}
else
{
sessionFactory = tmpSessionFactory
.ExposeConfiguration(BuildSchema)
.ExposeConfiguration(UpdateSchema)
.CurrentSessionContext<T>()
.BuildSessionFactory();
LazyInitializer.AlternativeConstructor(_configuration);
}
return sessionFactory;
}
catch (Exception ex)
{
LoggingFactory.GetLogger().LogError("[NHibernateSessionHelper.InitializeSessionFactory()]", ex);
throw;
}
}
private static Configuration CreateConfiguration()
{
string privateBinPath = BeforeConfiguration();
MsSqlConfiguration msSqlConfiguration = null;
msSqlConfiguration = MsSqlConfiguration.MsSql2012
.ConnectionString(SoNGHelper.GetConnectionString())
.Dialect<CustomMsSqlDialect>()
.AdoNetBatchSize(100);
if (SoNGSettings.isDBShowSql)
{
msSqlConfiguration.ShowSql();
}
FluentConfiguration fluentConfiguration = Fluently.Configure()
.Database(
msSqlConfiguration
);
if (SoNGSettings.isDBShowDiagnostics)
{
CheckFileDirectory(SoNG.Infrastructure.SoNGSettings.DB.DdDirectory,
SoNG.Infrastructure.SoNGSettings.DB.DbDiagnosticsFile);
fluentConfiguration.Diagnostics(x => x.Enable().OutputToFile(SoNG.Infrastructure.SoNGSettings.DB.DbDiagnosticsFile));
}
else
{
fluentConfiguration.Diagnostics(x => x.Disable());
}
Configuration configuration = fluentConfiguration.BuildConfiguration();
AfterConfiguration(privateBinPath);
return configuration;
}
private static string BeforeConfiguration()
{
if (!LoggingFactory.IsInitialized())
{
log4net.Config.XmlConfigurator.Configure();
}
//Backup PrivateBinPath
string privateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
//Erase PrivateBinPath
AppDomain.CurrentDomain.ClearPrivatePath();
AppDomain.CurrentDomain.SetupInformation.PrivateBinPath = String.Empty;
//Add only "bin" path
AppDomain.CurrentDomain.AppendPrivatePath(AppDomain.CurrentDomain.BaseDirectory + "bin");
AppDomain.CurrentDomain.SetupInformation.PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory + "bin";
return privateBinPath;
}
private static void AfterConfiguration(string privateBinPath)
{
//Erase PrivateBinPath
AppDomain.CurrentDomain.ClearPrivatePath();
//Add PrivateBinPath backuped
AppDomain.CurrentDomain.AppendPrivatePath(privateBinPath);
AppDomain.CurrentDomain.SetupInformation.PrivateBinPath = privateBinPath;
}
提前感谢您的帮助。
编辑:https://groups.google.com/g/nhibernate-development/c/560IBMajvvw[][1]我发现这段对话证实了我的观点,即nhibernate在select子句中管理null引用,但没有很好地理解最终答案,因为即使在我的映射中我指定引用不应为null,并且最终为null,nhibernat也会继续在我的测试解决方案中正确管理案例。。。
我刚刚理解,事实上,当Property_A为null并且Property_B被转移到可为null的类型(例如字符串(时,我们可以编写x.Property_A.Property_B。但是,如果Property_B被转移到不可为null的类型(例如int(,那么我们将收到著名的null引用异常。