簡體   English   中英

FluentNhibernate - 處理引用 null 引用的查詢

[英]FluentNhibernate - Handle query that refers to a null reference

我在 .net Core 和 in.Net 框架中測試了 NHibernate,似乎請求 null 引用是受管理的,並且不會引發 null 引用,例如通過檢索:x.Property_A.Property_B 當 Property_A 為 null 時。

在另一個具有不同配置的項目中,這種情況不受管理,如果 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 並且最終它是,nhibernate 繼續將案例正確地管理到我的測試解決方案中......

剛剛明白,其實我們可以寫x.Property_A.Property_B,當Property_A為null,Property_B轉為可空類型(例如string)。 但是,如果 Property_B 被轉換為不可空類型(例如 int),那么我們將收到著名的 null 引用異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM