这里我使用多线程和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连接放回池中。
我怀疑您将时间用作主键或唯一约束。如果是,那是你的问题,你应该使用identity
或uniqueidentifier
。
Identity将更具可读性,因为它将是升序数字值。它还很有用,因为它通常会告诉您记录是按什么顺序插入的,这在以后可能会很有用。
Uniqueidentifier的优点是您可以事先选择它,而不是等待数据库提供的结果。
对于日志类型的应用程序,我建议使用标识列。我在过去遇到过LINQ to SQL DataContexts记住我以前提交的对象,并试图在下次提交时再次插入它们的问题。听起来你可能会遇到类似的事情。
我想出的解决方案是处理旧的DataContext,并在每次调用SubmitChanges()之后重新开始使用一个新的DataContext。