一尘不染

顺序引导发生器

c#

有什么方法可以获取Sql Server 2005+ Sequential Guid生成器的功能,而无需插入记录以在往返或重新调用本地Win
dll调用时将其读回?我看到有人回答了使用rpcrt4.dll的方法,但是我不确定这是否可以在托管环境中进行生产。

编辑: 使用@John
Boker的答案,我试图将其变成更多的GuidComb生成器,而不是依赖于最后生成的Guid而不是重新开始。那是种子而不是从Guid.Empty开始

public SequentialGuid()
{
    var tempGuid = Guid.NewGuid();
    var bytes = tempGuid.ToByteArray();
    var time = DateTime.Now;
    bytes[3] = (byte) time.Year;
    bytes[2] = (byte) time.Month;
    bytes[1] = (byte) time.Day;
    bytes[0] = (byte) time.Hour;
    bytes[5] = (byte) time.Minute;
    bytes[4] = (byte) time.Second;
    CurrentGuid = new Guid(bytes);
}

我基于这些评论

// 3 - the least significant byte in Guid ByteArray 
        [for SQL Server ORDER BY clause]
// 10 - the most significant byte in Guid ByteArray 
        [for SQL Server ORDERY BY clause]
SqlOrderMap = new[] {3, 2, 1, 0, 5, 4, 7, 6, 9, 8, 15, 14, 13, 12, 11, 10};

这看起来像是我想用DateTime为guid植入种子的方式,还是看起来应该反向执行并从SqlOrderMap索引的末尾开始反向工作?我不会太担心它们是否会在每次创建初始guid时出现分页中断,因为它只会在应用程序回收期间发生。


阅读 302

收藏
2020-05-19

共1个答案

一尘不染

这个人想出了一些顺序建议,这是一个链接

http://developmenttips.blogspot.com/2008/03/generate-sequential-guids-for-
sql.html

相关代码:

public class SequentialGuid {
    Guid _CurrentGuid;
    public Guid CurrentGuid {
        get {
            return _CurrentGuid;
        }
    }

    public SequentialGuid() {
        _CurrentGuid = Guid.NewGuid();
    }

    public SequentialGuid(Guid previousGuid) {
        _CurrentGuid = previousGuid;
    }

    public static SequentialGuid operator++(SequentialGuid sequentialGuid) {
        byte[] bytes = sequentialGuid._CurrentGuid.ToByteArray();
        for (int mapIndex = 0; mapIndex < 16; mapIndex++) {
            int bytesIndex = SqlOrderMap[mapIndex];
            bytes[bytesIndex]++;
            if (bytes[bytesIndex] != 0) {
                break; // No need to increment more significant bytes
            }
        }
        sequentialGuid._CurrentGuid = new Guid(bytes);
        return sequentialGuid;
    }

    private static int[] _SqlOrderMap = null;
    private static int[] SqlOrderMap {
        get {
            if (_SqlOrderMap == null) {
                _SqlOrderMap = new int[16] {
                    3, 2, 1, 0, 5, 4, 7, 6, 9, 8, 15, 14, 13, 12, 11, 10
                };
                // 3 - the least significant byte in Guid ByteArray [for SQL Server ORDER BY clause]
                // 10 - the most significant byte in Guid ByteArray [for SQL Server ORDERY BY clause]
            }
            return _SqlOrderMap;
        }
    }
}
2020-05-19