WCF,GridViews,Callbacks和ExecuteReaders异常的严重问题

时间:2010-06-13 22:42:55

标签: c# linq wcf

我有这个让我疯狂的问题。

我有一个项目要在星期四之前交付。基本上是一个由三个组件组成的应用程序,它们在WCF中相互通信。

我有一个控制台应用程序和一个Windows窗体应用程序。控制台应用程序是连接到数据库的服务器。您可以通过Windows窗体客户端向其添加记录,该窗体客户端通过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 bla东西。我不知道是怎么回事。请指教。

1 个答案:

答案 0 :(得分:1)

这很可能是因为您宣布您的DatabaseLINQConnectionDataContext是静态的。这是一个大禁忌!当变量是静态的时,它在所有线程(请求)之间共享。这是一个很大的问题,因为DataContext存储了有关您所做的更改的工作单元信息,请您进行更改。

为每个客户端初始化一个DatabaseLINQConnectionDataContext,否则您将遇到类似这样的错误。尝试在数据访问周围的database块中初始化using