Entity framework core EF是如何同时拯救数千个实体的? 太长,读不下去了

Entity framework core EF是如何同时拯救数千个实体的? 太长,读不下去了,entity-framework-core,Entity Framework Core,如果我这样称呼EF: dbcontext.Update(newEntityA); dbContext.Save(); dbcontext.Update(newEntityB); dbContext.Save(); 所有这些都在

如果我这样称呼EF:

dbcontext.Update(newEntityA);
dbContext.Save();
dbcontext.Update(newEntityB);
dbContext.Save();
所有这些都在<1毫秒内成功完成,它将执行多少个INSERT语句?两个插入,每个插入有X个参数,或者一个插入有2X个参数,一行值是
(…),(…)

如果第一次插入因eg PK违规而失败,是否会更改答案

长版本 我有一个非常简单的应用程序,可以将数据从RabbitMQ移动到Azure SQL数据库。该应用程序看起来像这样(我去掉了大部分设置/记录调用):

1.4兆字节的数据组成了参数行,超过2096个参数

我很想知道EF是如何一次保存大约232个绘图命令的。我也很好奇为什么这是日志中的第一件事

我怀疑跟踪的实体是通过
Update()
调用添加到的,并保存在
Save()
调用中。如果
Save()
失败,则实体在跟踪的实体列表中保持未保存状态,并且当处理另一个队列消息并添加
Update()
时,将再次尝试
Save()
——这次列表中有两个实体,因此9个参数将变为18。。以此类推,直到要保存的实体图变大

是这样吗

有没有想过为什么我没有看到一系列错误消息,其中参数的数量不断增加,一直到2096?实际上,将最小日志记录级别重新配置为信息后,日志中的第一个条目有2096个参数


是否有可能立即获取日志级别更改,但azure管理面板重新启动服务的请求在稍后处理?在日志中的最后一次大规模查询之后,我看到“线程被中止”,然后服务立即恢复正常,一次插入一个实体。我认为两个EF都会合并db写入,因此如果在很短的时间内出现另一个
Save()
,它不会立即执行
Save()
。。或者是日志级别的变化会立即反映出来,因此第一个日志条目是应用程序仍在其旧对象列表中运行的最后几秒钟的jsut。重新启动应用程序删除了整个未保存的实体集,这些实体允许事情正常进行

由于PK冲突,EF无法保存实体。因为db上下文是单例的,所以每次尝试时跟踪的实体列表都在不断增长;将添加更多实体,但第一个实体仍无法保存


我更改了DB上下文的范围,以便在处理来自队列的消息的每个周期中重新创建它。这样,在更新dbcontext时,未正确保存的实体将被遗忘(我们不关心它们是否丢失,因为它们已损坏),这阻止了它被困在一个有大量积压的失败实体上,这与上下文无关。如果将代码包装到事务中会发生什么?你描述的SaveChanges周围的行为似乎发生了变化。事实上,我怀疑不会有什么变化。它有点“隐含事务性”,因为它只是一个包含2096个参数的update语句,而不是一个事务中包含9个参数的“显式事务性”——232条insert语句。事实上,在日志的后面,每次执行都有更多的insert语句——两个表和一个insert语句,如
insert A VALUES(@p0,@p1),(@p2,@p3);插入B值(@p4),(@p5)-除了那里还有数千个参数。奇怪的是,如果EF无法保存实体,那么EF在没有显式事务调用的情况下是实现全部还是什么都没有,这就是您的问题(不是数千个参数)。我真的什么都没有,我只是假设你在什么地方丢失了一些输出。
class Program
{

    private static IConfigurationRoot _configuration;
    private static IConsumer _consumer;
    private static ConsumerDbContext _dbContext;


    static void Main(string[] args)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

        _configuration = builder.Build();

        _dbContext = new ConsumerDbContext(...configblah...);
        _consumer = new RabbitMqConsumer(...configblah...);
        _consumer.Connect();
        _consumer.ReceivedMessage += ConsumerOnReceivedMessage;

    }


    private static void ConsumerOnReceivedMessage(object sender, MessageArgs messageArgs)
    {
        try{

            var model = JsonConvert.DeserializeObject<DrawingModel>(messageArgs.Message.ToString());

            if (model != null)
            {
                var drawing = _dbContext.Drawings.FirstOrDefault(x => x.Id == model.DrawingId);
                if (drawing != null)
                {
                    if (drawing.DrawingCommandModel != null)
                    {
                        var command = new DrawingCommandEntity(model.DrawingCommandModel);
                        command.Id = model.DrawingCommandId;
                        _dbContext.Add(command);
                    }
                    drawing.LastExecutedCommandId = model.DrawingCommandId;
                    drawing.CurrentState = model.DrawingState;
                    _dbContext.Update(drawing);
                    _dbContext.SaveChanges();
                }
                _logger.LogInformation("success ...");
            }
        }
        catch (Exception e)
        {
            _logger.LogInformation("fail .....");
        }
    }
}
date,level,message
2019-09-20T11:52:02,Inf,fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
2019-09-20T11:52:02,Inf,"      Failed executing DbCommand (2,689ms) [Parameters=  .... 1.4 megabytes of data snipped ... ]
2019-09-20T11:52:02,Inf,      SET NOCOUNT ON;,
2019-09-20T11:52:02,Inf,"      INSERT INTO [DrawingCommands] ([Id], [CommandType], [CreatedDate], [CurrentState], [CustomerId], [ObjectsIds], [PreviousState], [ToolType], [DrawingId])"
2019-09-20T11:52:02,Inf,"      VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8),",
2019-09-20T11:52:02,Inf,"      (@p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17),",
2019-09-20T11:52:02,Inf,"      (@p18, @p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26),",
2019-09-20T11:52:02,Inf,"      (@p27, @p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35),",
2019-09-20T11:52:02,Inf,"      (@p36, @p37, @p38, @p39, @p40, @p41, @p42, @p43, @p44),",
2019-09-20T11:52:02,Inf,"      (@p45, @p46, @p47, @p48, @p49, @p50, @p51, @p52, @p53),",
2019-09-20T11:52:02,Inf,"      (@p54, @p55, @p56, @p57, @p58, @p59, @p60, @p61, @p62),",
2019-09-20T11:52:02,Inf,"      (@p63, @p64, @p65, @p66, @p67, @p68, @p69, @p70, @p71),",
2019-09-20T11:52:02,Inf,"      (@p72, @p73, @p74, @p75, @p76, @p77, @p78, @p79, @p80),",
2019-09-20T11:52:02,Inf,"      (@p81, @p82, @p83, @p84, @p85, @p86, @p87, @p88, @p89),",
2019-09-20T11:52:02,Inf,"      (@p90, @p91, @p92, @p93, @p94, @p95, @p96, @p97, @p98),",
2019-09-20T11:52:02,Inf,"      (@p99, @p100, @p101, @p102, @p103, @p104, @p105, @p106, @p107),",

...

2019-09-20T11:52:02,Inf,"      (@p2088, @p2089, @p2090, @p2091, @p2092, @p2093, @p2094, @p2095, @p2096);",