将 Nhibernate Castle.ActiveRecord 迁移到 EFCore HiLo

问题描述

我们目前正在将旧的 OR 映射器迁移到 EF Core。直到现在我们使用 http://www.castleproject.org/projects/activerecord 或使用 HiLo 算法的映射器。解释是: https://github.com/castleproject-deprecated/ActiveRecord/blob/master/docs/primary-key-mapping.md

现在我们要切换到 EF Core 并尝试使用相同的算法。但是没有太多解释 HiLo 算法在 Nhibernate/ActiveRecord 中是如何工作的。我尽量避免 Id 冲突。

据我所知,Hi 值是在一个数据库中配置的: 从 hibernate_unique_key 中选择 next_hi 值:746708 我认为 maxLow 值是 Int16.MaxValue

在这种情况下,EFCore 的序列应该是:

CREATE SEQUENCE [dbo].[DBSequenceHiLo] 
 AS [bigint]
 START WITH (select next_hi from hibernate_unique_key + Int16.MaxValue)
 INCREMENT BY Int16.MaxValue
 MINVALUE -9223372036854775808
 MAXVALUE 9223372036854775807
 CACHE 
GO

ActiveRecord HiLo 算法究竟是如何工作的?什么是增量值?价值的起点是什么?迁移需要一些时间,是否可以与相同的 HiLo 算法并行运行?

解决方法

据我所知。不可能对 ActiveRecord 和 EF Core 使用完全相同的算法。一个使用 Sequence ,另一个使用表格。所以你不能同时使用 OR Mapper。但是你可以为EF Core创建一个没有ID冲突的序列,之后你就不能使用ActiveRecord了。

要获取 INCREMENT BY 值,只需启动当前应用程序。使用应用程序创建数据库条目。停下来。再次启动并创建第二个条目。因为您停止了应用程序,所以 Lo/cache 是空的,它会获得下一个 hi 值。这两个 ID 之间的区别是 Active Record 的“INCREMENT BY”值。就我而言,它是 2^17。我认为默认值应该是 2^15,但我还没有看到任何关于它的信息。

为了获得起始值,我创建了一个 SQL 脚本,以获取数据库的最高 Id。这是我的脚本(仅当您的 PK 名为 Id 并且仅适用于 sql 时才有效。)

DECLARE @tables TABLE(tablename nvarchar(max) NOT NULL);
                DECLARE @name nvarchar(max)
                DECLARE @maxid bigint
                DECLARE @currentid bigint
                DECLARE @query nvarchar(max);
                        DECLARE @sSQL nvarchar(500);
                        DECLARE @ParmDefinition nvarchar(500);

                        set @maxid = 0

                insert into @tables
                SELECT TABLE_NAME
                FROM INFORMATION_SCHEMA.TABLES
                WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG = 'BB_Vision'

                While(Select Count(*) From @tables) > 0
                Begin

                    Select Top 1 @name = tablename From @tables

                    IF EXISTS(SELECT 1 FROM sys.columns
                                WHERE Name = N'Id'

                                AND Object_ID = Object_ID(@name))

                    BEGIN
                        SELECT @sSQL = N'SELECT @retvalOUT = MAX(ID) FROM ' + @name;  
                        SET @ParmDefinition = N'@retvalOUT bigint OUTPUT';

                        EXEC sp_executesql @sSQL,@ParmDefinition,@retvalOUT=@currentid OUTPUT;

                        IF @currentid > @maxid
                        BEGIN

                            set @maxid = @currentid

                        END
                    END

                    Delete @tables Where @name = tablename
                End

                select @maxid+1

现在您可以创建您的 EF Core 序列。以下是如何使用它的说明: https://www.talkingdotnet.com/use-hilo-to-generate-keys-with-entity-framework-core/

之后您不应再使用 ActiveRecord,否则您必须使用更高的起始值重新创建序列。

由于迁移需要一些时间,而且您仍将主要为当前 OR 映射器创建一些功能/错误修复,因此最好在本地数据库上将 ActiveRecord Hi 值设置为更大的值。因此,您可以在同一个数据库上使用两者。但我不会在生产中使用它

update hibernate_unique_key set next_hi = next_hi + next_hi

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...