BIML中RootNode无法读取已定义数据库连接的问题咨询
BIML静态定义的数据库连接无法通过RootNode访问的问题
问题背景
刚接触BIML,遇到如下问题:在BIML中静态定义了名为POC_BIML_1的数据库连接,但在BimlScript中调用RootNode.DbConnections["POC_BIML_1"]返回null,RootNode.Connections.Count()结果为0。通过SchemaManager.CreateConnectionNode(代码场景2)能临时解决,但不清楚静态定义的连接为何无法生效。
使用环境:VS2019(SQL Server Integration Services Projects 3.16)+ 最新版BimlExpress
原始BIML代码
<Biml xmlns="http://schemas.varigence.com/biml.xsd"> <Connections> <Connection Name="POC_BIML_1" ConnectionString="Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;"/> </Connections> <!-- Scenario 1: RootNode.Connections --> <# var sourceConnection1 = RootNode.DbConnections["POC_BIML_1"]; if (sourceConnection1 == null ) { #> <!--sourceConnection1 is null. RootNode.Connections.Count = <#=RootNode.Connections.Count() #> --> <#} else { var sourceMetadata1 = sourceConnection1.GetDatabaseSchema(); foreach (var table in sourceMetadata1.TableNodes) { #> <!-- <#=table.Name#>" -->! <# } }#> <!-- Scenario 2: SchemaManager.CreateConnectionNode --> <# var sourceConnection2 = SchemaManager.CreateConnectionNode("POC_BIML_2", @"Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;"); var sourceMetadata2 = sourceConnection2.GetDatabaseSchema(); foreach (var table in sourceMetadata2.TableNodes) { #> <!--<#=table.Name#>"-->! <#} #> </Biml>
运行结果
<Biml xmlns="http://schemas.varigence.com/biml.xsd"> <Connections> <Connection Name="POC_BIML_1" ConnectionString="Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;"/> </Connections> <!-- Scenario 1: RootNode.Connections --> <!--sourceConnection1 is null. RootNode.Connections.Count = 0 --> <!-- Scenario 2: SchemaManager.CreateConnectionNode --> <!--care_provider_import_histories"-->! <!--care_provider_metrics"-->! <!--care_providers"-->! <!--care_services"-->! </Biml>
原因分析
核心原因是BIML的执行顺序:
- BimlScript(
<# ... #>包裹的代码块)会优先执行,而静态定义的<Connections>节点要等所有BimlScript执行完毕后,才会被加载到RootNode中。所以在脚本执行阶段,RootNode还未包含静态定义的连接,导致访问返回null。 SchemaManager.CreateConnectionNode是直接在内存中创建连接节点,不受静态BIML节点加载顺序的限制,因此能立即被脚本访问并生效。
解决办法
如果需要在BimlScript中访问静态定义的连接,可采用以下两种方式:
方式1:提前加载静态连接到SchemaManager
在脚本执行前,通过SchemaManager.ImportBiml加载包含连接定义的BIML内容,确保连接在脚本执行前被加载到RootNode:
<Biml xmlns="http://schemas.varigence.com/biml.xsd"> <Connections> <Connection Name="POC_BIML_1" ConnectionString="Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;"/> </Connections> <!-- 提前加载静态连接到SchemaManager --> <# // 导入当前BIML的连接定义部分 var connectionBiml = @"<Biml xmlns='http://schemas.varigence.com/biml.xsd'><Connections><Connection Name='POC_BIML_1' ConnectionString='Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;'/></Connections></Biml>"; SchemaManager.ImportBiml(connectionBiml); var sourceConnection1 = RootNode.DbConnections["POC_BIML_1"]; if (sourceConnection1 == null ) { #> <!--sourceConnection1 is null. RootNode.Connections.Count = <#=RootNode.Connections.Count() #> --> <#} else { var sourceMetadata1 = sourceConnection1.GetDatabaseSchema(); foreach (var table in sourceMetadata1.TableNodes) { #> <!-- <#=table.Name#>" -->! <# } }#> <!-- Scenario 2: SchemaManager.CreateConnectionNode --> <# var sourceConnection2 = SchemaManager.CreateConnectionNode("POC_BIML_2", @"Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;"); var sourceMetadata2 = sourceConnection2.GetDatabaseSchema(); foreach (var table in sourceMetadata2.TableNodes) { #> <!--<#=table.Name#>"-->! <#} #> </Biml>
方式2:拆分连接与脚本到不同文件
将连接定义单独放在一个BIML文件(比如Connections.biml),然后在包含脚本逻辑的BIML文件中通过<Import>节点引用该文件,这样RootNode会提前加载连接定义:
Connections.biml
<Biml xmlns="http://schemas.varigence.com/biml.xsd"> <Connections> <Connection Name="POC_BIML_1" ConnectionString="Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;"/> </Connections> </Biml>
ScriptLogic.biml
<Biml xmlns="http://schemas.varigence.com/biml.xsd"> <Import File="Connections.biml"/> <!-- Scenario 1: RootNode.Connections --> <# var sourceConnection1 = RootNode.DbConnections["POC_BIML_1"]; if (sourceConnection1 == null ) { #> <!--sourceConnection1 is null. RootNode.Connections.Count = <#=RootNode.Connections.Count() #> --> <#} else { var sourceMetadata1 = sourceConnection1.GetDatabaseSchema(); foreach (var table in sourceMetadata1.TableNodes) { #> <!-- <#=table.Name#>" -->! <# } }#> <!-- Scenario 2: SchemaManager.CreateConnectionNode --> <# var sourceConnection2 = SchemaManager.CreateConnectionNode("POC_BIML_2", @"Data Source=.;Initial Catalog=POC_BIML;Provider=SQLNCLI11;Integrated Security=SSPI;"); var sourceMetadata2 = sourceConnection2.GetDatabaseSchema(); foreach (var table in sourceMetadata2.TableNodes) { #> <!--<#=table.Name#>"-->! <#} #> </Biml>
内容的提问来源于stack exchange,提问作者WojtekG
相关产品推荐
相关产品推荐

