2010-06-13 53 views
1

我有這個問題讓我瘋狂。WCF,GridViews,Callbacks和ExecuteReaders異常的嚴重問題

我有一個項目要在星期四之前交付。基本上是一個由三個組件組成的應用程序,它們在WCF中相互通信。

我有一個控制檯應用程序和一個Windows窗體應用程序。控制檯應用程序是連接到數據庫的服務器。您可以通過通過WCF與服務器連接的Windows Forms客戶端向其添加記錄。

客戶端的代碼:

namespace BankAdministratorClient 
{ 
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext = false)] 
    public partial class Form1 : Form, BankServverReference.BankServerCallback 
    { 
     private BankServverReference.BankServerClient server = null; 
     private SynchronizationContext interfaceContext = null; 

     public Form1() 
     { 
      InitializeComponent(); 
      interfaceContext = SynchronizationContext.Current; 

      server = new BankServverReference.BankServerClient(new InstanceContext(this), "TcpBinding"); 

      server.Open(); 
      server.Subscribe(); 

      refreshGridView(""); 
     } 

     public void refreshClients(string s) 
     { 
      SendOrPostCallback callback = delegate(object state) 
      { refreshGridView(s); }; 
      interfaceContext.Post(callback, s); 
     } 

     public void refreshGridView(string s) 
     { 
      try 
      { 
       userGrid.DataSource = server.refreshDatabaseConnection().Tables[0]; 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.ToString()); 
      } 
     } 

     private void buttonAdd_Click(object sender, EventArgs e) 
     { 
      server.addNewAccount(Int32.Parse(inputPIN.Text), Int32.Parse(inputBalance.Text)); 
     } 

     private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
     { 
      try 
      { 
       server.Unsubscribe(); 
       server.Close(); 
      }catch{} 
     } 

    } 
} 

服務器的代碼:

namespace SSRfinal_tcp 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(MessageHandler.dataStamp("The server is starting up")); 

      using (ServiceHost server = new ServiceHost(typeof(BankServer))) 
      { 
       server.Open(); 
       Console.WriteLine(MessageHandler.dataStamp("The server is running")); 
       Console.ReadKey(); 
      } 
     } 
    } 

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults = true)] 
    public class BankServer : IBankServerService 
    { 
     private static DatabaseLINQConnectionDataContext database = new DatabaseLINQConnectionDataContext(); 
     private static List<IBankServerServiceCallback> subscribers = new List<IBankServerServiceCallback>(); 

     public void Subscribe() 
     { 
      try 
      { 
       IBankServerServiceCallback callback = OperationContext.Current.GetCallbackChannel<IBankServerServiceCallback>(); 
       if (!subscribers.Contains(callback)) 
        subscribers.Add(callback); 
       Console.WriteLine(MessageHandler.dataStamp("A new Bank Administrator has connected")); 
      } 
      catch 
      { 
       Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has failed to connect")); 
      } 
     } 

     public void Unsubscribe() 
     { 
      try 
      { 
       IBankServerServiceCallback callback = OperationContext.Current.GetCallbackChannel<IBankServerServiceCallback>(); 
       if (subscribers.Contains(callback)) 
        subscribers.Remove(callback); 
       Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has been signed out from the connection list")); 
      } 
      catch 
      { 
       Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has failed to sign out from the connection list")); 
      } 
     } 

     public DataSet refreshDatabaseConnection() 
     { 
      var q = from a in database.GetTable<Account>() 
        select a; 
      DataTable dt = q.toTable(rec => new object[] { q }); 
      DataSet data = new DataSet(); 
      data.Tables.Add(dt); 

      Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has requested a database data listing refresh")); 

      return data; 
     } 

     public void addNewAccount(int pin, int balance) 
     { 
      Account acc = new Account() 
      { 
       PIN = pin, 
       Balance = balance, 
       IsApproved = false 
      }; 
      database.Accounts.InsertOnSubmit(acc); 
      database.SubmitChanges(); 
      database.addNewAccount(pin, balance, false); 
      subscribers.ForEach(delegate(IBankServerServiceCallback callback) 
      { 
       callback.refreshClients("New operation is pending approval."); 
      }); 

     } 
    } 
} 

這是非常簡單的,它適用於一個單一的窗口。但是,當您打開客戶端窗口的多個實例並嘗試添加新記錄時,執行插入操作的窗口會因ExecuteReader錯誤而崩潰,並且「需要打開且可用的連接,連接的當前狀態正在連接」bla bla東西。我不知道發生了什麼事。請指教。

回答

1

這很可能是因爲您已宣佈您的DatabaseLINQConnectionDataContext爲靜態。這是一個很大的禁忌!當一個變量是靜態的,它在所有線程(請求)之間共享。這是一個巨大的問題,因爲DataContext存儲有關您所做的更改的工作單元信息。

爲每個客戶端初始化一個DatabaseLINQConnectionDataContext,否則會遇到類似這樣的錯誤。嘗試在數據訪問周圍的using塊中初始化database

+0

哇。哇哇!你剛剛救了我的一天。它的工作,它確實。我無法表達我多麼感激。謝謝! – barjed 2010-06-14 00:33:27