使用多线程时在DB中插入行?

时间:2011-04-15 13:01:45

标签: sql-server multithreading linq c#-4.0

这里我使用多线程和linq到sql。

我在这里上传了我的代码段:

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

邮件存储库类

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

当我在没有线程的情况下运行它然后它在包含线程之后工作正常我得到了以下错误消息:

错误:已添加具有相同键的项目。

提前致谢...:)

3 个答案:

答案 0 :(得分:3)

您无法以并发方式使用LINQ DataContext

  

任何实例成员都不是   保证是线程安全的。

因此,您需要序列化访问(锁定),这将是非常低效的,或者更好地在每个线程中使用单独的上下文:

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

我也希望,为了您自己的缘故,您的测试具有等待测试线程在关闭之前完成的实际逻辑......当然,在您的存储库中正确实现IDisposable并处理上下文以便数据库连接放回池中。

答案 1 :(得分:0)

我怀疑您使用时间作为主键或作为唯一约束。如果是,那就是您的问题,您应该使用identityuniqueidentifier

身份将更具可读性,因为它将是升序数值。它也很有用,因为它通常会告诉您插入记录的顺序,以后可能会有用。

Uniqueidentifier的优势在于您可以事先选择它,而不是等待数据库为您提供的内容。

对于日志记录类型的应用程序,我建议使用标识列。

答案 2 :(得分:0)

过去我遇到过问题,LINQ to SQL DataContexts记住我之前提交的对象,并在下次提交时尝试再次插入它们。听起来你可能会碰到类似的东西。

我提出的解决方案是在每次调用SubmitChanges()之后处理旧的DataContext并重新开始。