Luiso
Luiso

Reputation: 4113

NLog DatabaseTarget Install not working

Am using NLog 4.2.2 and asp net 5. All my NLog configurations are on code. I need to deploy my project and want to make sure the appropriate SqlServer Table and StoredProcedure are created. I'm using the DatabaseTarget.Install() method like this:

dbTarget.InstallDdlCommands.Clear();
dbTarget.InstallDdlCommands.Add(new DatabaseCommandInfo
{
    ConnectionString = connectionString,
    CommandType = System.Data.CommandType.Text,
    IgnoreFailures = false,
    Text = $@"CREATE TABLE [dbo].[{TableName}] (
           [ID] [int] IDENTITY(1,1) NOT NULL,
           [MachineName] [nvarchar](200) NULL,
           [SiteName] [nvarchar](200) NOT NULL,
           [Logged] [datetime] NOT NULL,
           [Level] [varchar](5) NOT NULL,
           [UserName] [nvarchar](200) NULL,
           [Message] [nvarchar](max) NOT NULL,
           [Logger] [nvarchar](300) NULL,
           [Properties] [nvarchar](max) NULL,
           [ServerName] [nvarchar](200) NULL,
           [Port] [nvarchar](100) NULL,
           [Url] [nvarchar](2000) NULL,
           [Https] [bit] NULL,
           [ServerAddress] [nvarchar](100) NULL,
           [RemoteAddress] [nvarchar](100) NULL,
           [Callsite] [nvarchar](300) NULL,
           [Exception] [nvarchar](max) NULL,
         CONSTRAINT [PK_dbo.Log] PRIMARY KEY CLUSTERED ([ID] ASC) 
           WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
        ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY];"
});

dbTarget.InstallDdlCommands.Add(new DatabaseCommandInfo
{
    ConnectionString = connectionString,
    CommandType = System.Data.CommandType.Text,
    IgnoreFailures = false,
    Text = $@"CREATE PROCEDURE [dbo].[{ProcName}] (
              @machineName nvarchar(200),
              @siteName nvarchar(200),
              @logged datetime,
              @level varchar(5),
              @userName nvarchar(200),
              @message nvarchar(max),
              @logger nvarchar(300),
              @properties nvarchar(max),
              @serverName nvarchar(200),
              @port nvarchar(100),
              @url nvarchar(2000),
              @https bit,
              @serverAddress nvarchar(100),
              @remoteAddress nvarchar(100),
              @callSite nvarchar(300),
              @exception nvarchar(max)
            ) AS
            BEGIN
              INSERT INTO [dbo].[{TableName}] (
                [MachineName],
                [SiteName],
                [Logged],
                [Level],
                [UserName],
                [Message],
                [Logger],
                [Properties],
                [ServerName],
                [Port],
                [Url],
                [Https],
                [ServerAddress],
                [RemoteAddress],
                [CallSite],
                [Exception]
              ) VALUES (
                @machineName,
                @siteName,
                @logged,
                @level,
                @userName,
                @message,
                @logger,
                @properties,
                @serverName,
                @port,
                @url,
                @https,
                @serverAddress,
                @remoteAddress,
                @callSite,
                @exception
              );
            END"
});

using (var context = new InstallationContext())
{
    if (dbTarget.IsInstalled(context) != true)
        dbTarget.Install(context);
}

But when I run my code I get this exception System.ArgumentNullException | Value cannot be null. |Parameter name: type

I have seen this question and I think I'm doing what they say but still doesn't work for me. I know the rest of the code to be good as DB logging works just fine once I manually create the Table and StoredProcedure

Upvotes: 3

Views: 457

Answers (1)

Luiso
Luiso

Reputation: 4113

After a while I opened an issue in github and I got the answer from there. Turns out that, as of now, when you programmatically create a configuration file (as I was) you have to manually call configuration.Install(installationContext) in order for the different Targets to be actually initialized, as a side effect it will also run the Install method of the Targets that have it. So all the above code needs to do is

 // Target configuration as is (except for the installation part)
 config.AddTarget(dbTarget);

 using(var context = new InstallationContext())
 {
     config.Install(context);
 }

if there are more than one target though I think config.Install(context) should be called after all target (or at least most of them) have being added as it initializes all registered targets and runs Install on them.

Upvotes: 1

Related Questions