1

我有一个在我的应用程序中使用的记录器类,包括请求和线程。记录器由每个 Log.Insert(string text) 的数据库插入组成。记录器是一个静态类,每次调用 Insert 都会创建一个新的数据库上下文。可能有很多对 Insert 的调用,并且同时有很多数据库上下文不利于优化。(我有时会遇到数据库超时,因为跨应用程序的 sql 操作太多 - 所以确实需要优化)。

这可以通过在 Logger 类的静态成员中创建和存储单个数据库上下文来优化,该成员仅用于 Log.Inserts?或者这会失败吗?

记录器类的简化版本;

[Table]
public class Log
{
   [Column]
   public string Text { get; set; }

   private static DataContext DatabaseContextInsert { get; set; }

   public static void Insert(string text)
   {
      if (DatabaseContextInsert == null)
      {
          DatabaseContextInsert = DataContextHelper.GetDataContext();            
      }

      var log = new Log { Text = text };          

      lock (DatabaseContextInsert)
      {
        DatabaseContextInsert.GetTable<Log>().InsertOnSubmit(log);
        DatabaseContextInsert.SubmitChanges();
      }
   }
}
4

1 回答 1

2

使用静态记录器将是一个非常糟糕的主意。除了同步问题之外,您还会遇到永久保存在数据上下文中的所有项目的问题(数据上下文喜欢保留它已经看到的对象)。

您提到您认为大量数据上下文不利于优化,但连接可能已经在池化(默认情况下它会这样做),因此数据上下文实际上并不是很“重”。

如果不需要同步插入日志条目,我会很想做一些事情,比如将新的日志项放入队列(同步访问),并有一个工作线程每 10 秒清空一次队列,基本上是在做类似的事情:

// adding an item
lock(queue) { queue.Enqueue(text); }


// worker code, every 10 seconds
List<string> items = new List<string>();
lock(queue) {
    while(queue.Count != 0) items.Add(items.Dequeue);
}
using(var ctx = CreateContext()) {
    foreach(var text in items) {
        ctx.Logs.InsertOnSubmit(new Log { Text = text });
    }
    ctx.SubmitChanges();
}

然后只有一个线程正在写入数据库,并且您的事务要少得多。

如果这不是一个选项,并且您需要同步进行,那么坦率地说,我会将几个级别降为“dapper”之类的东西,即

using(var conn = CreateOpenConnection()) {
    conn.Execute("insert [Log]([Text]) values(@text)", new {text});
}

这完全消除了对数据上下文的需求更简单,并且无需考虑事务。

于 2012-06-15T07:06:58.283 回答