0

我正在编写一个许多玩家连接的游戏服务器。我将数据库加载到数据集(强类型)中。每次玩家登录时,我都会使用 TableAdapter 向 Messages 表添加一个新行。

code
        var newRow = _db.Messages.NewMessagesRow(); // _db is a strong-typed-dataset
        {
            newRow.Title = title;
            newRow.Text = text;
            newRow.ReceiverUID = receiverUID;
            newRow.Deleted = false;
        }

        // I lock the _db.Messages, so it happens one at a time
        lock ( _db.Messages ) 
        {
            _db.Messages.AddMessagesRow( newRow );
            _adapterMessages.Connection.Open();
            _adapterMessages.Update( newRow );
            newRow.MessageID = (Int64)_adapterMessages.GetIdentity();
            newRow.AcceptChanges();
            _adapterMessages.Connection.Close();
        }

NewMessagesRow() 和 AddMessagesRow() 由 VS 自动生成。我通过添加一个 DataSet 项(.xsd 文件)并将所有数据库表拖到其中来做到这一点。

        public MessagesRow NewMessagesRow() {
            return ((MessagesRow)(this.NewRow()));
        }
        public void AddMessagesRow(MessagesRow row) {
            this.Rows.Add(row);
        }

_db 是一个 DataSet(强类型,由 VS 自动生成) _db.Messages 是一个 DataTable。

在测试中,我得到

System.Data.NoNullAllowedException: Column 'Deleted' does not allow nulls.
   at System.Data.DataColumn.CheckNullable(DataRow row)
   at System.Data.DataTable.RaiseRowChanging(...)
   at System.Data.DataTable.SetNewRecordWorker(...)
   at System.Data.DataTable.InsertRow(...)
   at System.Data.DataRowCollection.Add(DataRow row)
   at Server.Database.MessagesDataTable.AddMessagesRow(MessagesRow row)

AddMessagesRow() 仅在上面的代码中被调用,我总是为 Deleted 列设置 false,但仍然收到此消息...

我不在其他任何地方使用 _adapterMessages,但还有其他可以同时使用的适配器(_adapterUsers、_adapterMatches 等)。

我不是每次都遇到异常,但是如果服务器运行一段时间(比如 > 30 分钟),大约有 1000 个并发玩家,它就会发生。

任何帮助或建议将不胜感激。谢谢 :)

4

1 回答 1

0

我找出了这个问题的根本原因。我认为 DataTable.NewRow() 是线程安全的,但事实并非如此。在任何表上调用 NewRow() 之前,我必须独占锁定。

所以上面的代码需要修改如下:

    lock ( _db.Messages )
    {
        var newRow = _db.Messages.NewMessagesRow();
        {
            newRow.Title = title;
            newRow.Text = text;
            newRow.ReceiverUID = receiverUID;
            newRow.Deleted = false;
        }

        _db.Messages.AddMessagesRow( newRow );
        _adapterMessages.Connection.Open();
        _adapterMessages.Update( newRow );
        newRow.MessageID = (Int64)_adapterMessages.GetIdentity();
        newRow.AcceptChanges();
        _adapterMessages.Connection.Close();
    }

这个问题可以参考google搜索结果。。

于 2010-10-08T08:05:24.203 回答