NLog数据库目标适用于.NET Core 2.0

3
我正在尝试使用.NET Core 2.0中的NLog将各种日志写入数据库和文件。问题是,将日志写入文件完美地运行,但是当尝试将日志写入数据库时,总是会出现以下错误:

2018-01-10 08:48:29.5666错误 Error initializing target 'Database Target[db]'. Exception: System.TypeLoadException: Could not load type 'System.Data.SqlClient' from assembly 'NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c'. at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive) at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName) at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark) at System.Type.GetType(String typeName, Boolean throwOnError) at NLog.Targets.DatabaseTarget.SetConnectionType() at NLog.Targets.DatabaseTarget.InitializeTarget() at NLog.Targets.Target.Initialize(LoggingConfiguration configuration)

但是我在项目中有 System.Data.SqlClient 如下:

<ItemGroup>
    <PackageReference Include="EPPlus.Core" Version="1.5.4" />
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.0-beta3" />
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.3" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Session" Version="2.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.1" PrivateAssets="All" />
    <PackageReference Include="NLog" Version="4.5.0-rc03" />
    <PackageReference Include="NLog.Web.AspNetCore" Version="4.5.0-rc2" />
    <PackageReference Include="System.ComponentModel" Version="4.3.0" />
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0-preview1-25914-04" />
    <PackageReference Include="System.Data.SqlClient" Version="4.4.2" />
</ItemGroup>

我的NLOG代码:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="info" internalLogFile="C:\*****\Log2\asdaf.log">
<targets>
    <target
        xsi:type="File"
        name="allfile"
        fileName="C:\*****\Logs\${shortdate}.log"
        layout="${longdate}|${event-properties:item=EventId.Id}|${uppercase:${level}}|${logger}|${message} ${exception}" >
    </target> 

    <target xsi:type="Database" name="db">
        <commandText>INSERT INTO [LogEntries](TimeStamp, Message, Level, Logger) VALUES(getutcdate(), @msg, @level, @logger)</commandText>
        <parameter name="@msg" layout="${message}" />
        <parameter name="@level" layout="${level}" />
        <parameter name="@logger" layout="${logger}" />
        <dbProvider>System.Data.SqlClient</dbProvider>
        <connectionString>*****</connectionString>
    </target>

    <target xsi:type="Null" name="blackhole" />
</targets>
<rules>
    <logger name="*" minlevel="Trace" writeTo="allOutputs" />
    <logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />
    <logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>

我在Github上搜索了这个问题,但是没有一种解决方案适用于我。从Nuget获取System.Data.SqlClient应该足够了,但不幸的是,Nlog.config需要其他东西,我找不出来是什么。


仅仅因为NuGet packages.config中有该包并不意味着它已经在你的项目中了。你的顶层.csproj项目也应该包含对System.Data.SqlClient的“PackageReference”。你还可以在构建后检查bin文件夹,看看DLL是否存在。 - StuartLC
我的 .csproj 文件中显示存在 System.Data.SqlClient - KaraKaplanKhan
此外,bin文件夹中还有System.Data.SqlClient.dll。在我看来,项目已经有了它,但NLog找不到它。 - KaraKaplanKhan
我的猜测是<dbProvider>的值不太对。NLog似乎试图将其作为自己程序集的资源查找(如错误消息所述),而它可以在“调用”程序集中找到它作为资源。也许文档可以帮助解决问题? - Fildor
以下是一个与程序相关的段落,如果您遇到了与此完全相同的错误,则有可能解决问题:使用 Microsoft.Data.Sqlite 的完全限定名称的示例(适用于 dotnet core 2.0):dbProvider="Microsoft.Data.Sqlite.SqliteConnection, Microsoft.Data.Sqlite, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60"所以您需要找到 System.Data.SqlClient 的等效项并使用它。 - Fildor
我认为这可能是由于提供程序的原因。但是我正在使用 System.Data.SqlClient,无论我搜索到哪里,所有人都像 <dbProvider>System.Data.SqlClient</dbProvider>provider="System.Data.SqlClient" 这样写提供程序。 - KaraKaplanKhan
2个回答

9

这是因为我在我的数据库目标中写入<dbProvider>System.Data.SqlClient</dbProvider>。看起来应该有人更新文档了。

顺便说一下,我不知道为什么删除dbProvider对我有用。

正常工作的代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="info" internalLogFile="C:\Users\maliozt\source\MyProjects\MapApplication\MapApplication\Log2\asdaf.log">
<targets>
    <target
    xsi:type="File"
    name="mapFile"
    fileName="C:\Users\maliozt\source\MyProjects\MapApplication\MapApplication\Logs\${shortdate}.log"
    layout="${longdate}|${event-properties:item=EventId.Id}|${uppercase:${level}}|${logger}|${message} ${exception}" >
    </target>

    <target 
    xsi:type="Database" 
    name="mapDataBase">
        <commandText>INSERT INTO MapApplication.dbo.LogEntries(TimeStamp, Message, Level, Logger) VALUES(GETDATE(), @message, @level, @logger)</commandText>
        <parameter name="@message" layout="${message}" />
        <parameter name="@level" layout="${level}" />
        <parameter name="@logger" layout="${logger}" />
        <!--<dbProvider>System.Data.SqlClient</dbProvider>-->
        <connectionString>Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False</connectionString>
    </target>
</targets>
<rules>
    <logger name="*" minlevel="Warn" writeTo="mapFile" />
    <logger name="*" minlevel="Error" writeTo="mapDataBase" />
</rules>
</nlog>

1
在使用Oracle数据库时,它对我不起作用。你能帮我解决这个问题吗? - Ankit Mori
我想做,但我没有足够的Oracle知识。也许你需要写一些不同的东西而不是“connectionString”。 - KaraKaplanKhan
仅删除dbProvider只适用于Sql Server,因为Sqlclient是默认提供程序。这也是为什么它不适用于Oracle的原因。对于Oracle,您需要提供dbProvider =“Oracle.ManagedDataAccess.Client.OracleConnection,Oracle.ManagedDataAccess”。请参见https://github.com/nlog/NLog/wiki/Database-target。 - Michel van Engelen
尝试了自定义目标和其他选项后,这个是我在.NET Core 7项目中与NLog和EF7一起工作的唯一解决方案。谢谢。 - Jaume

0
在我的情况下,我发现错误来自于表名。

无效的对象名称 'dbo.Journal'

我刚刚删除了“dbo”,它就可以工作了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接