6

Here I am using multi threading and linq to sql.

Here I upload my code snippet:

public class PostService
{ 
    MessageRepository objFbPostRespository = new MessageRepository();
    public void callthreads()
    {
        for (int i = 0; i < 100; i++)
        {
            Thread th = new Thread(postingProcess);
            th.Start();
        }
    }

    public void postingProcess()
    {
        objFbPostRespository.AddLog("Test Multithread", DateTime.Now);
    }
}

Message Repository class

class MessageRepository
{        
    DataClassesDataContext db_Context = new DataClassesDataContext();
    public void AddLog(string Message, DateTime CurrentDateTime)
    {
        FbMessgaeLog FbMessage = new FbMessgaeLog
        {
            Message = Message,
            Time = CurrentDateTime                
        };
        db_Context.FbMessgaeLogs.InsertOnSubmit(FbMessage);
        db_Context.SubmitChanges();
    }
}

When I run it without threads then it's work fine after include thread I was got following error msg:

Error: An item with the same key has already been added.

Thanks in advance...:)

3
  • 1
    What does your database use as its key here? Commented Apr 15, 2011 at 13:13
  • @Jens I would assume its a database identity column and that is the main issue Commented Apr 15, 2011 at 13:42
  • 2
    what is your requirement that make you choose the multithreading approach ? can't you use a queue to push items to write and return instantaneously, and let a background worker do the job in a sequential manner ? Commented Apr 15, 2011 at 14:03

3 Answers 3

3

You cannot use a LINQ DataContext in concurrent fashion:

Any instance members are not guaranteed to be thread safe.

Therefore you need to either serialize access (lock) which will be horribly inefficient, or better use a separate context in each thread:

public class PostService
{ 
    public void callthreads()
    {
        for (int i = 0; i < 100; i++)
        {
            Thread th = new Thread(postingProcess);
            th.Start();
        }
    }

    public void postingProcess()
    {
        using (MessageRepository objFbPostRespository = new MessageRepository())
        {
           objFbPostRespository.AddLog("Test Multithread", DateTime.Now);
        }
    }
}

I also hope, for your own sake, that your test has actual logic to wait for the test threads to complete before shutting down... And, of course, properly implement IDisposable in your repository and dispose the context so that the DB connection get placed back in the pool.

Sign up to request clarification or add additional context in comments.

Comments

0

I suspect you are using the time as the primary key or as a unique constraint. If so, that's your problem, you should use either an identity or a uniqueidentifier.

Identity will be more readable, since it will be ascending numeric values. It will also be useful since it will generally tell you in what order the records were inserted, which may be useful later on.

Uniqueidentifier has the advantage that you can choose it beforehand instead of waiting to see what the database gives you.

For a logging type application I would recommend an identity column.

Comments

0

I've had problems in the past with LINQ to SQL DataContexts remembering objects I had previously submitted, and attempting to insert them again the next time I submit. It sounds like you might be running into something similar.

The solution I came up with was to dispose the old DataContext and start over with a new one after each call to SubmitChanges().

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.