views:

30

answers:

1

I'm writing a game server to which many players connect. I load up the DB into a DataSet(strong typed). Every time a player logs in, I add a new row to Messages table using a TableAdapter.

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() and AddMessagesRow() is auto-generated by VS. I did it by adding a DataSet item(.xsd file) and dragging all the DB tables to it.

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

_db is a DataSet(strong-typed, auto-generated by VS) _db.Messages is a DataTable.

while in testing, I get

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() gets called only in the code above, and I always set false for Deleted column, but still gets this message...

I don't use _adapterMessages anywhere else, but there are other adapters (_adapterUsers, _adapterMatches,... etc) that could be used concurrently.

I don't get the exception every time, but if the server runs for sometime(like > 30 min) with about 1000 concurrent players, it happens.

Any help or advices will be greatly appreciated. Thanks :)

A: 

I figured out the root cause of this problem. I thought DataTable.NewRow() was thread-safe, but it's not. I have to lock exclusively before I call NewRow() on any tables.

so the code above needs to be changed like:

    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();
    }

You can refer to google search results on this issue..

wooohoh