2010-06-13 2 views
1

У меня есть эта проблема, которая сводит меня с ума.Серьезная проблема с исключениями WCF, GridViews, Callbacks и ExecuteReaders

У меня есть проект до четверга. В основном приложение объединяет три компонента, которые общаются друг с другом в WCF.

У меня есть одно консольное приложение и одно приложение Windows Forms. Консольное приложение - это сервер, подключенный к базе данных. Вы можете добавлять записи к нему через клиент Windows Forms, который соединяется с сервером через WCF.

Код для клиента:

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 бла. Я понятия не имею, что происходит. Пожалуйста, порекомендуйте.

ответ

1

Это скорее всего, потому что вы заявили, что ваш DatabaseLINQConnectionDataContext является статическим. Это БОЛЬШОЙ нет-нет! Когда переменная является статической, она используется для всех потоков (запросов). Это огромная проблема, потому что DataContext хранит информацию о вашей работе об изменениях, которые вы задали, и попросите их сделать их.

Инициализировать один DatabaseLINQConnectionDataContext на каждого клиента, иначе вы столкнетесь с такими ошибками. Попробуйте инициализировать database в блоке using вокруг ваших доступа к данным.

+0

Ничего себе. Просто вау. Ты только что спас мне день. Он работает, это действительно так. Я не могу выразить, насколько я благодарен. Благодаря! – barjed

Смежные вопросы