2012-06-15 89 views
1

我有一個記錄器類,遍及我的應用程序,在請求和線程中都使用。記錄器由每個Log.Insert(字符串文本)的數據庫插入組成。記錄器是一個靜態類,每次調用Insert時都會創建一個新的數據庫上下文。可能會有很多調用Insert,並且很多數據庫上下文同時不利於優化。 (我有時會因爲應用程序中的sql操作太多而導致數據庫超時 - 所以確實需要優化)。LINQ DataContext堅持很多插入的最佳實踐

這是否可以通過在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(); 
     } 
    } 
} 
+0

你想顯示一些代碼? –

+0

我認爲這將有助於你[http://stackoverflow.com/questions/2481956/linq-to-sql-datacontext-for-a-web-application][1] [1]:HTTP ://stackoverflow.com/questions/2481956/linq-to-sql-datacontext-for-a-web-application – Charlie

+0

添加示例類 – Eilev

回答

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(); 
} 

然後只有一個線程正在寫入數據庫,並且您的事務少得多。

如果不是一個選項,你需要同步做,那麼坦率地說我幾級下降到類似「短小精悍」,即

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

其去除需要一個數據上下文在所有,要簡單得多,並將交易從考慮中刪除。

+0

保存日誌條目是非常重要的 - 所以具有延遲的線程將不會一個完美的解決方案(需要跟蹤爲什麼在應用程序熔化的例子,這可能會阻止線程完成)。 但是,簡單的SQL添加可能是一個很好的解決方案,沒有必要跟蹤添加的對象,因爲更新的將要改變。但是有沒有一種簡單的LINQ到SQL的方式來創建這個簡單的插入?我比「文本」有更多的字段,因此使用對象而不是SQL字符串進行插入是可取的。 – Eilev