Serious problem with WCF, GridViews, Callbacks and ExecuteReaders exceptions.
- by barjed
Hi, I have this problem that is driving me insane.
I have a project to deliver before Thursday. Basically an app consiting of three components that communicate with each other in WCF.
I have one console app and one Windows Forms app. The console app is a server that's connected to the database. You can add records to it via the Windows Forms client that connectes with the server through the WCF.
The code for the client:
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{}
}
}
}
The code for the server:
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.");
});
}
}
}
This is really simple and it works for a single window. However, when you open multiple instances of the client window and try to add a new record, the windows that is performing the insert operation crashes with the ExecuteReader error and the " requires an open and available connection. the connection's current state is connecting" bla bla stuff. I have no idea what's going on. Please advise.