Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将EF DatabaseContext注入自定义ScopedService_C#_Asp.net Core 2.0_Ef Core 2.0 - Fatal编程技术网

C# 将EF DatabaseContext注入自定义ScopedService

C# 将EF DatabaseContext注入自定义ScopedService,c#,asp.net-core-2.0,ef-core-2.0,C#,Asp.net Core 2.0,Ef Core 2.0,在我看来,作用域服务内注入的EF的性能非常低 在这种情况下,我很有可能错误地使用EF,但我无法找到正确的描述/文档说明如何在这种情况下使用EF(将其注入自定义托管服务) 在EasyRabbit/startup.cs(配置服务)中注册了以下服务: // db services.AddDbContext<ApplicationDbContext>(options => { options.UseSqlServer("Server=localhost; Database=Ra

在我看来,作用域服务内注入的EF的性能非常低

在这种情况下,我很有可能错误地使用EF,但我无法找到正确的描述/文档说明如何在这种情况下使用EF(将其注入自定义托管服务)

在EasyRabbit/startup.cs(配置服务)中注册了以下服务:

// db
services.AddDbContext<ApplicationDbContext>(options =>
{
    options.UseSqlServer("Server=localhost; Database=RabbitTest; MultipleActiveResultSets=true; User ID=sa; Password=Admin1234");
});

// default REST Api
services.AddMvc();
// Configuration for Rabbit connector
services.Configure<RabbitConfig>(Configuration.GetSection("RabbitConfig"));
// Rabbit Connector
services.AddSingleton<RabbitConnector>();
// Subscriber which listens if some new message arrives
services.AddSingleton<IHostedService, GenericHostedSubscriber<CalculatorInputs>>();

// Every arival message is then processed in following scope
// ApplicationDbContext dbContext is injected into this RabbitSubscribers.Adder
services.AddScoped<IScopedProcessingService<CalculatorInputs>, RabbitSubscribers.Adder>();
整个代码可以在

谢谢

复制步骤
  • 从以下位置克隆当前存储库:
  • 从以下位置安装RabbitMQ:
  • 安装MSSQL
  • 将EasyRabbit/startup.cs中的连接器更改为DB(第31行)
  • 转到文件夹RandomNumberPairGenerator并运行命令dotnet run几秒钟,然后您可以使用ctrl+c取消它(它会在RabbitMQ队列中创建一些消息)
  • 运行EasyRabbit项目,观察每秒处理多少条消息 *。如果已安装RabbitMQ管理,则可以在上查看性能(默认登录名:guest;密码:guest)

  • 编辑:

    以下是当前测量的性能:

  • EF异步内部加法器.cs-230/s
  • EF无异步内部加法器。cs-100/s
  • ADO.NET异步-1300/s
  • 不带异步的ADO.NET-150/s
  • EF注入上下文异步-40/s
  • 无异步的EF注入上下文-65/s
  • 情景1、2、3、4。将adder.cs作为单例


    情景5、6。他们将adder.cs作为作用域服务

    嗯,ORM总是比较慢。在本例中,您只需插入一条记录。通过创建一个对象并将其添加到上下文中,您将产生大量开销。我建议您创建一个存储过程,将其作为函数插入并导入到上下文中。我怀疑这会大大加快速度。另一种选择是每隔一段时间收集批处理并进行大容量保存,以尽量减少对数据库的调用次数。我没想到会这么慢(比direct sql insert慢22倍)。几分钟前,我试图改变代码,而不是注入db上下文,我直接在HandleMessageAsync方法中使用EF上下文,平均性能提高到230条消息/秒。仍然比直接插入慢5倍,但比注入的EFWell快5倍,注入过程也会产生开销。看起来,
    Adder
    可能是一个单例。考虑到您当前的设计,我建议您:将
    Adder
    设置为单例(如果可能的话),并继续添加到
    HandleMessageAsync
    的上下文中,但在收集到100个
    Calculation
    对象之前,不要调用
    SaveChangesSync
    。否则,使用导入的函数。
    namespace EasyRabbit.RabbitSubscribers
    {
        public class Adder : IScopedProcessingService<CalculatorInputs>
        {
            private ILogger<Adder> _logger;
            private ApplicationDbContext _db;
    
            public Adder(ApplicationDbContext dbContext, ILogger<Adder> logger)
            {
                _logger = logger;
                _db = dbContext;
    
            }
    
            public async Task HandleMessageAsync(CalculatorInputs message)
            {
    
                Console.WriteLine($"Calculator: [{message.FirstNumber}] + [{message.SecondNumber}] = {message.FirstNumber + message.SecondNumber}");
                await _db.Calculations.AddAsync(new Calculation()
                {
                    FirstNumber = message.FirstNumber,
                    SecondNumber = message.SecondNumber,
                    Result = message.FirstNumber + message.SecondNumber
                });
    
                await _db.SaveChangesAsync();
    
            }
        }
    }
    
    public static class DB
    {
        private static string _connectionString = "Server=localhost; Database=RabbitTest; MultipleActiveResultSets=true; User ID=sa; Password=Admin1234";
    
    
        public static void AddRecord(MyDBObject myDBObject)
        {
            using (SqlConnection con = new SqlConnection(_connectionString))
            {
                using (SqlCommand cmd = new SqlCommand("insert into test (FirstNumber, SecondNumber, Result) values (@FirstNumber, @SecondNumber, @Result)", con))
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.Parameters.AddWithValue("@FirstNumber", myDBObject.FirstNumber);
                    cmd.Parameters.AddWithValue("@SecondNumber", myDBObject.SecondNumber);
                    cmd.Parameters.AddWithValue("@Result", myDBObject.Result);
                    con.Open();
                    cmd.ExecuteNonQuery();
                    con.Close();
                }
    
            }
        }
    }
    
    public class MyDBObject
    {
        public int FirstNumber { get; set; }
        public int SecondNumber { get; set; }
        public int Result { get; set; }
    }