sql server语言 - 在使用多线程时在数据库中插入行



这里我使用多线程和linq to 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();
    }
}

当我在没有线程的情况下运行它时,在包含线程后它的工作很好,我得到了以下错误消息:

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

不能以并发方式使用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并释放上下文,以便将DB连接放回池中。

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

Identity将更具可读性,因为它将是升序数字值。它还很有用,因为它通常会告诉您记录是按什么顺序插入的,这在以后可能会很有用。

Uniqueidentifier的优点是您可以事先选择它,而不是等待数据库提供的结果。

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

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

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

相关内容

  • 没有找到相关文章

最新更新