DeleteOnSubmit LINQ exception "Unable to add object with key that is already in use"

edit: in case someone is asking a question, the actionhandler calls the code that creates and uses the same type of datacontext, in case this may have anything to do with this behavior. the code does not apply to the MatchUpdateQueue table, but I think I should mention this just in case.

double edit: everyone who answered was right! I answered the defendant, who underwent most of my survey. fixing the problem allowed another problem to emerge (hidden inside the handler) that caused the same exception. oops!

I am having trouble deleting items in LINQ. Calling DeleteOnSubmit in the code below throws a LINQ exception with the message "Unable to add an object with a key that is already in use." I'm not sure what I'm doing wrong here, he starts pushing me against the wall. The primary key is just an integer auto-increment column, and I have no other problems until I try to remove the item from the database queue. Hopefully I'm doing something hurtfully inhibited here, which is easy to notice for everyone who isn't me!

static void Pacman()
{
    Queue<MatchUpdateQueue> waiting = new Queue<MatchUpdateQueue>();

    events.WriteEntry("matchqueue worker thread started");

    while (!stop)
    {
        if (waiting.Count == 0)
        {
            /* grab any new items available */
            aDataContext db = new aDataContext();
            List<MatchUpdateQueue> freshitems = db.MatchUpdateQueues.OrderBy(item => item.id).ToList();

            foreach (MatchUpdateQueue item in freshitems)
                waiting.Enqueue(item);
            db.Dispose();
        }
        else
        {
            /* grab & dispatch waiting item */
            MatchUpdateQueue item = waiting.Peek();
            try
            {
                int result = ActionHandler.Handle(item);
                if (result == -1)
                    events.WriteEntry("unknown command consumed : " + item.actiontype.ToString(), EventLogEntryType.Error);

                /* remove item from queue */
                waiting.Dequeue();

                /* remove item from database */
                aDataContext db = new aDataContext();
                db.MatchUpdateQueues.DeleteOnSubmit(db.MatchUpdateQueues.Single(i => i == item));
                db.SubmitChanges();
                db.Dispose();
            }
            catch (Exception ex)
            {
                events.WriteEntry("exception while handling item : " + ex.Message, EventLogEntryType.Error);
                stop = true;
            }
        }

        /* to avoid hammering database when there nothing to do */
        if (waiting.Count == 0)
            Thread.Sleep(TimeSpan.FromSeconds(10));
    }

    events.WriteEntry("matchqueue worker thread halted");
}
+3
source share
5 answers

You can do something with the effect

db.MatchUpdateQueues.DeleteOnSubmit(db.MatchUpdateQueues.Single(theItem => theItem == item));

, Attach.. attach , , , .

+2

:

aDataContext db = new aDataContext();
item = new MatchUpdateQueue { id=item.id }; // <- updated
db.MatchUpdateQueues.Attach(item);
db.MatchUpdateQueues.DeleteOnSubmit(item);
db.SubmitChanges();

datacontext, , db.

0

while using :

Queue<MatchUpdateQueue> waiting = new Queue<MatchUpdateQueue>();
events.WriteEntry("matchqueue worker thread started");
while (!stop)
{
    using (var db = new aDataContext())
    {
      if (waiting.Count == 0)
      {
        /* grab any new items available */
           List<MatchUpdateQueue> freshitems = db.MatchUpdateQueues
                                                 .OrderBy(item => item.id)
                                                 .ToList();
           foreach (MatchUpdateQueue item in freshitems)
                waiting.Enqueue(item);
      }
      ...
   }
}
0

db.Dispose(). , , , . , / , .

Also, do not delete the second such data context, since the exception will not cause this code. Use the using keyword, which will necessarily cause a deletion regardless of whether an exception has occurred. Also take an element from db to remove it (to avoid the need for serialization / deserialization / attachment).

using (aDataContext db = new aDataContext())
{
   var dbItem = db.MatchUpdateQueues.Single(i => i.Id == item.Id);
   db.MatchUpdateQueues.DeleteOnSubmit(dbItem);
   db.SubmitChanges();
}
0
source

try this if your TEntity (here Area) Primary Key is of type Identity column; Only this, without any changes to your SP or model:

public void InitForm()
{
    'bnsEntity is a BindingSource and cachedAreas is a List<Area> created from dataContext.Areas.ToList()
    bnsEntity.DataSource = cachedAreas;
    'A nominal ID
    newID = cachedAreas.LastOrDefault().areaID + 1;
    'grdEntity is a GridView
    grdEntity.DataSource = bnsEntity;
}

private void tsbNew_Click(object sender, EventArgs e)
{
    var newArea = new Area();
    newArea.areaID = newID++;
    dataContext.GetTable<Area>().InsertOnSubmit(newArea);
    bnsEntity.Add(newArea);
    grdEntity.MoveToNewRecord();
}
0
source

Source: https://habr.com/ru/post/1705357/


All Articles