EF6 两个上下文与具有两个等待的单个上下文

EF6 two contexts vs. single context with two awaits(EF6 两个上下文与具有两个等待的单个上下文)
本文介绍了EF6 两个上下文与具有两个等待的单个上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下哪一种是提高性能的更好方法?注意:对于某些操作,我最多可以执行五个独立的查询.

Which of these is a better approach for performance? Note: For some operations I have up to five independent queries to execute.

var foo = await context.foos.ToListAsync();
var bar = await context.bars.ToListAsync();

对比

var fooTask = context1.foos.ToListAsync();
var barTask = context2.bars.ToListAsync();
await Task.WhenAll(fooTask , barTask);

不用等待就使用相同的上下文会很棒,但 this answer 提到这是不可能的.

It would be great to use the same context without awaits, but this answer mentions that is not possible.

推荐答案

正如您所发现的,DbContext 不是线程安全的,因此真正并行运行查询的唯一选择是为每个线程创建一个新的 DbContext/任务.

As you found out, the DbContext is not thread safe, therefore the only option to really run the queries in parallel would be to create a new DbContext for each Thread/Task.

创建新 DbContext 的开销非常低.https://msdn.microsoft.com/en-us/library/cc853327.aspx

The overhead of creating a new DbContext is pretty low. https://msdn.microsoft.com/en-us/library/cc853327.aspx

由于对象将来自不同的 DbContext,为了进一步提高性能,我建议您也使用 NoTracking()

Since the object will come from different DbContexts and to further increase performance I recommend you also use NoTracking()

我用我拥有的数据库做了一个简单的测试程序:

I made a simple test program with a database I had:

class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Warming up db context...");

        using (var db = new TestDbContext())
        {
            Console.WriteLine(db.AuditLogItems.ToList().Count);
        }

        // 1st run
        RunAsync();
        RunTasked();

        // 2nd run
        RunAsync();
        RunTasked();

        Console.ReadKey();
    }

    private static void RunAsync()
    {
        Task.Run(async () =>
        {
            var sw = Stopwatch.StartNew();
            List<AuditLogItem> list1;
            List<AuditLogItem> list2;

            using (var db = new TestDbContext())
            {
                list1 = await db.AuditLogItems.AsNoTracking().ToListAsync();
                list2 = await db.AuditLogItems.AsNoTracking().ToListAsync();
            }

            sw.Stop();
            Console.WriteLine("Executed {0} in {1}ms. | {2}", "Async", sw.ElapsedMilliseconds, list1.Count + " " + list2.Count);

        }).Wait();
    }

    private static void RunTasked()
    {
        Func<List<AuditLogItem>> runQuery = () =>
        {
            using (var db = new TestDbContext())
            {
                return db.AuditLogItems.AsNoTracking().ToList();
            }
        };

        var sw = Stopwatch.StartNew();
        var task1 = Task.Run(runQuery);
        var task2 = Task.Run(runQuery);

        Task.WaitAll(task1, task2);

        sw.Stop();
        Console.WriteLine("Executed {0} in {1}ms. | {2}", "Tasked", sw.ElapsedMilliseconds, task1.Result.Count + " " + task2.Result.Count);
    }
}

输出是:

Warming up db context...
5908
Executed Async in 293ms. | 5908 5908
Executed Tasked in 56ms. | 5908 5908
Executed Async in 194ms. | 5908 5908
Executed Tasked in 32ms. | 5908 5908

所以是的,选项 2 更快...

So yes, option 2 is faster...

这篇关于EF6 两个上下文与具有两个等待的单个上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)