实体框架上下文中的多线程
本文关键字:多线程 上下文 框架 实体 | 更新日期: 2023-09-27 17:59:10
我有一个相当大的查询,我想在多个线程中执行,以最大限度地提高性能。以下是我的代码的概括:
public ActionResult ControllerAction()
{
using(var context = new DataEntities())
{
var person = context.People.First(p => p.UserId == User.Identity.UserId);
var model = new PersonViewModel(person);
return View(model);
}
}
// Inside the PersonViewModel class
public List<ApplicationViewModel> Applications { get; set; }
public List<MessageViewModel> Messages { get; set; }
public PersonViewModel(Person person)
{
var applicationsThread = new Thread(PopulateApplications);
applicationThread.Start(person);
var messagesThread = new Thread(PopulateMessages);
messagesThread.Start(person);
// Other code to be done while application/messages threads run
applicationThread.Join();
messagesThread.Join();
}
private void PopulateApplications(object personObject)
{
var person = personObject as Person;
Applications = person.Applications.Where(/*logic*/);
}
private void PopulateMessages(object personObject)
{
var person = personObject as Person;
Messages = person.Messages.Where(/*logic*/);
}
但是,当我点击控制器操作时,只有应用程序被填充。我猜这与尝试从多个线程访问实体上下文对象的属性有关,但这些线程都不应该相互冲突。切换线程顺序会导致填充消息,但应用程序将保持未填充状态,这一事实强化了这一假设。
编辑,这是使用克里尔加答案的更新版本:
private static async void GenerateAbilities(int personId)
{
using (var context = new BattleGameEntities())
{
var personAbilities = await context
.persons
.First(p => p.personId == personId)
.Messages
.OrderBy(m => m.Date).Select(a => new MessageViewModel
{
//Logic
}).ToListAsync();
}
}
正确。造成这种情况的根本原因是DbContext对DataReader进行操作。一次只能打开其中一个。
如果您使用的是.NET 4.5和EF 6,那么您可以使用新的Async()
方法来自动使用多个线程来完成这一切。基本上,它只是任何方法的后缀。这是一篇关于使用这些新方法的文章。
var applications = context.Applications.ToListAsync();
var messages = context.Messages.ToListAsync();
如果您使用的是.NET 4.0,那么您必须在每个线程中创建一个新的Context,并分别维护它们。在这一点上,您还会遇到对象来自不同上下文的问题。
是的,我知道这篇文章是用VB.NET编写的,但语法相似。无论出于何种原因,他们所有的文章都是用这种语言写的。