Серьезная проблема с исключениями WCF, GridViews, Callbacks и ExecuteReaders - PullRequest
1 голос
/ 14 июня 2010

У меня есть проблема, которая сводит меня с ума.

У меня есть проект, который нужно выполнить до четверга.В основном это приложение, состоящее из трех компонентов, которые взаимодействуют друг с другом в 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, и «требуется открытое и доступное соединение. Текущее состояние соединения подключается»бла вещиЯ понятия не имею, что происходит.Пожалуйста, сообщите.

1 Ответ

1 голос
/ 14 июня 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...