如何在运行时更改NLog目标的连接字符串?

Vla*_*irs 3 c# logging nlog asp.net-web-api

在我的WebAPI应用程序中,我试图Application_BeginRequest根据我的自定义标头值登录到几个单独的数据库中。

为了实现这个目标我试图修改targetNlog.config,像这样:

<target name="database" 
        xsi:type="Database" 
        connectionString="${gdc:item=myConnectionstring}" 
        commandText="..sql command..">..params..</target>
Run Code Online (Sandbox Code Playgroud)

Application_BeginRequest我试图这样设置myConnectionstring

GlobalDiagnosticsContext.Set("myConnectionString", connectionString);
Run Code Online (Sandbox Code Playgroud)

但这不起作用,并且在NLog的internalLogFile错误中显示:

2015-02-19 12:12:48.8776 Error Error when writing to database System.InvalidOperationException: The ConnectionString property has not been initialized.
   at System.Data.SqlClient.SqlConnection.PermissionDemand()
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()
   at NLog.Targets.DatabaseTarget.OpenConnection(String connectionString)
   at NLog.Targets.DatabaseTarget.WriteEventToDatabase(LogEventInfo logEvent)
   at NLog.Targets.DatabaseTarget.Write(LogEventInfo logEvent)
Run Code Online (Sandbox Code Playgroud)

我尝试将以下参数写入db(使用恒定连接字符串配置):

<parameter name="@cn" layout="${gdc:myConnectionstring}"/>
<parameter name="@cn1" layout="${gdc:item=myConnectionstring}"/>
Run Code Online (Sandbox Code Playgroud)

但是它们似乎是空的,但是,当我调试WebApi Action并引发期望写入数据库的错误时,该操作会GlobalDiagnosticsContext.Get("myConnectionString")返回预期值。

我做错了什么?为什么我可以在中看到期望值,GlobalDiagnosticsContext.Get("myConnectionString")${gdc:item=myConnectionstring}解析为空字符串?

Vla*_*irs 6

找到了另一种方法来实现这一目标:

var databaseTarget = (DatabaseTarget)LogManager.Configuration.FindTargetByName("database");
databaseTarget.ConnectionString = connectionString;
LogManager.ReconfigExistingLoggers();
Run Code Online (Sandbox Code Playgroud)

但是仍然不清楚为什么GlobalDiagnosticsContext东西不起作用..


bon*_*ter 5

感谢您的解决方案!

不过,如果您想使用异步数据库目标,则需要首先获取包装的目标:

DatabaseTarget databaseTarget;
var target = LogManager.Configuration.FindTargetByName("database");
if (target is AsyncTargetWrapper)
    databaseTarget = (target as AsyncTargetWrapper).WrappedTarget as DatabaseTarget;
else
    databaseTarget = target as DatabaseTarget;
if (databaseTarget == null)
    throw new NullReferenceException("Can't find DatabaseTarget with name 'database'");

databaseTarget.ConnectionString = connectionStringSelected.ConnectionString;
LogManager.ReconfigExistingLoggers();
Run Code Online (Sandbox Code Playgroud)