内存优化表(EF 核心 5)不支持保存点

Posted

技术标签:

【中文标题】内存优化表(EF 核心 5)不支持保存点【英文标题】:Savepoint is not supported with memory optimized tables (EF core 5) 【发布时间】:2021-03-12 06:38:33 【问题描述】:

使用新功能 SavePoints 将 EF 核心版本 3.1 升级到 5(使用事务手册时自动创建)

我在 SQL Server 2016 中有一个名为“内容”的内存优化表。

当我调用“SaveChanges”命令时,系统会抛出异常“内存优化表不支持创建保存点”。如何关闭保存点?

注意:如果我使用 TransactionScope 则通过成功。

请给我解决这种情况的方法 https://docs.microsoft.com/en-us/ef/core/saving/transactions

【问题讨论】:

不要关闭保存点,不要使用显式事务。仅当您使用显式事务时才使用保存点。但在大多数情况下,这不是必需的。 SaveChanges已经使用内部事务。 DbContext 已经实现了 Unit-of-Work 语义,因此不需要显式事务。 为什么还要使用显式事务?您是否尝试使用“通用存储库”anti模式?在这种情况下,您应该检查 No need for Repository and Unit-of-Work with EF Core 和 Repository is the new Singleton 感谢您的回答。我正在为我的项目使用 unitofwork 模型。我有 2 个不强制外键的表 A 和 B。我将新记录添加到表 A 并保存到 DB 并生成 id。之后,我使用之前从表 A 生成的 id 将信息记录添加到表 B 中。为了数据完整性,我必须将其全部包装在一个显式事务中 这是你的错误。你不需要额外的工作单元,你已经有了一个非常好的工作单元。 I have to wrap it all in one explicit transaction for data integrity 不,您没有,您在使用存储库反模式时破坏了完整性,现在您必须通过添加另一个事务来掩盖这一点。不要那样做 阅读我发布的链接。在现有 UoW 之上,您不需要另一个 UoW。通过在每次“CRUD”操作后尝试执行一个SaveChanges,您破坏了 UoW 并不得不引入一个事务。然而,您的 INSERT 可以轻松执行 30 次更新和 60 次删除以及另外 41 次插入,而不是您认为自己编写的单个 Insert 【参考方案1】:

我想在没有外键的两个表中插入行。

在 startup.cs 文件中

public void ConfigureServices(IServiceCollection services)
    
        services.AddHealthChecks();
        services.AddDbContext<wUtilityContentContext>(opts => opts.UseSqlServer(
           Algorithm.Decrypt(Configuration["ConnectionStrings:wUtilityContent_ConnectionString"]),
           b => b.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name)));

        services.AddUnitOfWorkPool(optionsBuilder =>
        
            optionsBuilder.AddUnitOfWork<wUtilityContentContext>("Content");
        );
        services.AddScoped<IContentUow, ContentUow>();
        services.AddScoped<AuditCoreLog>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        ....
    

在 ContentService.cs 文件中

public class ContentServices : ContentServiceBase

    private readonly AuditCoreLog _auditLog;
    private readonly IContentUow _contentUow;
    public ContentServices(IContentUow contentUow, AuditCoreLog auditLog)
    
        _contentUow = contentUow;
        _auditLog = auditLog;
    
    public override Task<MessageResponse> CategoryInsertUpdate(CategoryInsertUpdate_Request request, ServerCallContext context)
    
        var response = new MessageResponse()  ;
        try
        
            int _RESPONSE_EXISTED_CATE = -2;
            int _RESPONSE_NOT_EXISTS_CATE = -3;
            int _nHotOrder = 0;
            var findnHotOrder = _contentUow.Category.Where(p => p.ParentId == request.ParentId).ToList();
            if (findnHotOrder != null && findnHotOrder.Count > 0)
               _nHotOrder = findnHotOrder.Max(x => x.OrderNo).GetValueOrDefault();
            var insertCategory = _contentUow.Category.Add(new TblCategory()
            
                    ParentId = request.ParentId,
                    Alias = request.Alias,
                    OrderNo = _nHotOrder + 1,
                    Status = request.Status,
                    CreatedDate = DateTime.Now,
                    CreatedUser = request.CreatedUser,
                    SystemId = request.SystemId,
                    ImageUrl = request.ImageUrl
            );

                _contentUow.SaveChanges(); //savechange to DB -> get id identity
                var _categoryId = insertCategory.Entity.Id;
                var insertCategoryContent_vi = _contentUow.CategoryContent.Add(new TblCategoryContent()
                
                    CategoryId = _categoryId,
                    CategoryName = request.CategoryNameVi,
                    CategoryContent = request.CategoryContentVi,
                    LanguageId = (int)PaymentApps_PaymentLanguage.VN
                );

                var insertCategoryContent_en = _contentUow.CategoryContent.Add(new TblCategoryContent()
                
                    CategoryId = _categoryId,
                    CategoryName = request.CategoryNameEn,
                    CategoryContent = request.CategoryContentEn,
                    LanguageId = (int)PaymentApps_PaymentLanguage.EN
                );
            _contentUow.SaveChanges();
            _contentUow.CommitTransaction();
            response.ResponseStatus = ErrorCodes.SUCCESS;
        
        catch (Exception ex)
        
            response.ResponseStatus = ErrorCodes.SYSTEM_ERROR;
            _contentUow.RollbackTransaction();
        
    

【讨论】:

以上是关于内存优化表(EF 核心 5)不支持保存点的主要内容,如果未能解决你的问题,请参考以下文章

流分析是不是支持输出到 SQL Server 内存优化表?

Mysql优化

项目新增内存表优化软件速度

SQLServer 2014 内存优化表

SQL Server 内存优化表 - 与临时表相比性能较差

使用 flyway - 如何部署内存优化表