问题描述
|
在这里,我使用多线程和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();
}
}
当我在没有线程的情况下运行它时,在包含线程之后,它的工作正常,出现以下错误消息:
错误:具有相同键的项目已被添加。
提前致谢...:)
解决方法
您不能以并发方式使用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并处理上下文,以便获得数据库连接放回游泳池。
,我怀疑您将时间用作主键或唯一约束。如果是这样,那就是您的问题,您应该使用identity
或uniqueidentifier
。
身份将更具可读性,因为它将是升序的数值。它也将很有用,因为它通常会告诉您记录插入的顺序,以后可能会有用。
Uniqueidentifier的优点是您可以预先选择它,而不必等待查看数据库为您提供的内容。
对于日志记录类型的应用程序,我建议您使用一个身份列。
,过去,LINQ to SQL DataContexts在记住我以前提交的对象并在下次提交时尝试再次插入它们时遇到了问题。听起来您可能遇到了类似的情况。
我想出的解决方案是处理旧的DataContext,并在每次调用SubmitChanges()之后从新开始。