2014-10-27 1 views
1

Я пытаюсь использовать SQLite с NLog, чтобы я мог хранить ведение журнала в базе данных SQLite, а не в плоском файле. Я последовал за хорошим учебным пособием, но даже тогда мой код не включен, работает как и ожидалось.Как использовать SQLite с NLog в .NET

Мой App.config файл:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <connectionStrings> 
    <add name="SQLite" connectionString="Data Source=Log.db3;Version=3;" providerName="System.Data.SQLite" /> 
    </connectionStrings> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" /> 
    </startup> 
    <system.data> 
    <DbProviderFactories> 
     <remove invariant="System.Data.SQLite" /> 
     <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> 
    </DbProviderFactories> 
    </system.data> 
</configuration> 

И это мой NLog.config файл

<?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"> 
    <targets> 
    <target name="file" xsi:type="File" 
      layout="${longdate} ${logger} ${message}" 
      fileName="${basedir}/logs/${shortdate}/${level}.txt" 
      keepFileOpen="false"/> 
    <target name="db" xsi:type="Database" keepConnection="false" 
      useTransactions="false" 
      dbProvider="System.Data.SQLite" 
      connectionString="Data Source=${basedir}\Log.db3;Version=3;" 
      commandText="INSERT into Log(Timestamp, Loglevel, Callsite, Message) values(@Timestamp, @Loglevel, @Callsite, @Message)"> 
     <parameter name="@Timestamp" layout="${longdate}"/> 
     <parameter name="@Loglevel" layout="${level:uppercase=true}"/> 
     <parameter name="@Callsite" layout="${callsite:filename=true}"/> 
     <parameter name="@Message" layout="${message}"/> 
    </target> 
    </targets> 
    <rules> 
    <logger name="*" minlevel="Trace" writeTo="db" /> 
    </rules> 
</nlog> 

И это мой код:

static class Program 
    { 
     static Logger log = LogManager.GetCurrentClassLogger(); 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      try 
      { 
       Application.EnableVisualStyles(); 
       Application.SetCompatibleTextRenderingDefault(false); 
       EnsureDb(); 
       log.Info("Logging like a boss"); 
       Application.Run(new Form1()); 
      } 
      catch (Exception ex) 
      { 
       throw; 
      } 

     } 

     private static void EnsureDb() 
     { 
      if (File.Exists("Log.db3")) 
       return; 

      using (SQLiteConnection connection = new SQLiteConnection(ConfigurationManager.ConnectionStrings["SQLite"].ToString())) 
      using (SQLiteCommand command = new SQLiteCommand(
       "CREATE TABLE Log (Timestamp TEXT, Loglevel TEXT, Callsite TEXT, Message TEXT)", 
       connection)) 
      { 
       connection.Open(); 
       command.ExecuteNonQuery(); 
      } 
     } 
    } 

Я скопировал этот код из Интернета, но, к сожалению, он не работает , Файл log.db3 всегда создается, но запись журнала не доходит до таблицы журналов. Как я могу это исправить?

+0

Что не работает? Получаете ли вы ошибку и т. Д.? – nemesv

+0

нет я не получаю сообщение об ошибке, log.db3 созданный файл, но таблица журнала всегда пустой – Shax

ответ

0

Для .NET 2.0 ядра я должен использовать:

dbProvider="Microsoft.Data.Sqlite.SqliteConnection, Microsoft.Data.Sqlite" 
1

Попробуйте добавить команду типа Text:

<target name="db" xsi:type="Database" 
     keepConnection="false" 
     useTransactions="false" 
     dbProvider="System.Data.SQLite" 
     connectionString="Data Source=${basedir}\Log.db3;Version=3;" 
     commandType="Text" 
     commandText="INSERT into Log(Timestamp, Loglevel, Callsite, Message) values(@Timestamp, @Loglevel, @Callsite, @Message)"> 

Кроме того, для целей отладки рассмотреть возможность использования LogManager.ThrowExceptions = true; в вашем Main - это может дать некоторые указания о том, что это не так. Он бросает NotSupportedException, который дал мне подсказку о CommandType:

Unhandled Exception: NLog.NLogRuntimeException: Exception occurred in NLog ---> 
System.NotSupportedException: Specified method is not supported. 
    at System.Data.SQLite.SQLiteCommand.set_CommandType(CommandType value) 
+1

Я последовал за ваше предложение и нашел ошибку, InnerException: NLog.NLogRuntimeException Message = Не удалось загрузить тип «System.Data .SQLite 'from assembly' NLog, Version = 3.1.0.0, Culture = neutral, PublicKeyToken = 5120e14c03d0593c '. – Shax

+0

Попробуйте 'System.Data.SQLite.EF6' как поставщика. – TarasB

+1

У меня также возникла проблема с исключением «Не удалось загрузить тип« System.Data.SQLite »из сборки« NLog, Version = ... »Для меня проблема заключалась в том, что у меня не было никаких DBProviderFactories в app.config. Я не могу этого сделать, потому что я использую NLog в сборке .NET, которая используется несколькими проектами, включая некоторые собственные приложения. Простое решение в NLog target указывает более полное имя типа для dbProvider вместо имени инварианта в приведенном выше примере. Поэтому строка должна выглядеть так: dbProvider = "System.Data.SQLite.SQLiteConnection, System.Data.SQLite" – MarkR