实体框架上下文中的多线程

本文关键字:多线程 上下文 框架 实体 | 更新日期: 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编写的,但语法相似。无论出于何种原因,他们所有的文章都是用这种语言写的。