1

我们目前正在将旧的 OR Mapper 迁移到 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 算法并行运行它?

4

1 回答 1

0

我所知道的。不可能对 ActiveRecord 和 EF Core 使用完全相同的算法。一个与 Sequence 一起工作,另一个与 table 一起工作。所以你不能同时使用 OR Mapper。但是您可以在没有 ID 冲突的情况下为 EF Core 创建一个序列,之后您就不能使用 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
于 2021-04-09T06:19:14.173 回答