t3chb0t t3chb0t - 1 month ago 6
C# Question

Is there a more efficient way to create nlog database targets?

I often create logs that have a lot of custom columns like:

<target xsi:type="Database" name="Log" dbProvider="System.Data.SqlClient" connectionString="...">
<commandText>
INSERT
INTO [dbo].[Log]([Foo], [Bar], ...)
VALUES(@FOO, @BAR, ...)
</commandText>
<parameter name="@FOO" layout="..." />
<parameter name="@BAR" layout="..." />
...
</target>


but I don't really like how I have to repeat the names of the columns three times for each of them. It's difficult to maintain and easy to make a mistake.

Is there an easier and more efficient way to create NLog database targets?

Can NLog infer the insert from the parameters alone? It would be great if I just could write the schema and table name, the parameters and the
INSERT
is pretty obvious so it actually could be build automatically. Is there such a mechanism yet?

I've added the
c#
tag because if there is a programmatic solution I prefer
c#
.

Answer

In addition to t3chb0t answer.

You could loop over all the database targets after the configuration changes:

private void Main() //or application_start
{
    //init
    GenerateDatabaseTargetQueries();

    //update when config changes
    LogManager.ConfigurationReloaded += (sender, args) => GenerateDatabaseTargetQueries();
}

public void GenerateDatabaseTargetQueries()
{
    var databaseTargets = LogManager.Configuration.AllTargets.OfType<DatabaseTarget>();
    foreach (var databaseTarget in databaseTargets)
    {
        //todo good init capacity for StringBuilder
        var queryBuilder = new StringBuilder();
        queryBuilder.Append("INSERT INTO [dbo].[Log]");
        foreach (var dbParameter in databaseTarget.Parameters)
        {
            //append all the parameters to the query
        }
        databaseTarget.CommandText = queryBuilder.ToString();
    }
}