C#系列-C#EF框架实现雪花主键(20)

 C#中,使用Entity Framework (EF) 框架并不直接涉及到主键的生成策略。主键的生成通常是在数据库层面或者在应用程序层面处理的。雪花主键(Snowflake ID)是一种在分布式系统中生成唯一ID的算法,它通常是由Twitter的雪花算法演变而来。

雪花主键的特点是在不依赖数据库的情况下,能够在分布式系统中生成全局唯一且有序的64位整数ID。这种ID通常用于大数据场景,因为它们可以有效地利用缓存、分片、以及分布式系统中的其他优化策略。

下面是一个简单的C#实现雪花主键生成器的例子:

csharp代码

public class SnowflakeIdGenerator

{

private const long epoch = 1288834974657L; // 起始时间戳(毫秒)

private const long workerIdBits = 5L; // 机器id所占的位数

private const long datacenterIdBits = 5L; // 数据中心id所占的位数

private const long maxWorkerId = -1L ^ (-1L << workerIdBits); // 支持的最大机器id数量

private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 支持的最大数据中心id数量

private const long sequenceBits = 12L; // 序列所占的位数

private const long workerIdShift = sequenceBits; // 机器ID左移位数

private const long datacenterIdShift = sequenceBits + workerIdBits; // 数据中心ID左移位数

private const long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; // 时间戳左移位数

private const long sequenceMask = -1L ^ (-1L << sequenceBits); // 序列掩码

private long workerId; // 机器ID

private long datacenterId; // 数据中心ID

private long sequence = 0L; // 序列

private long lastTimestamp = -1L; // 上次生成ID的时间戳

public SnowflakeIdGenerator(long workerId, long datacenterId)

{

if (workerId > maxWorkerId || workerId < 0)

{

throw new ArgumentException(string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId));

}

if (datacenterId > maxDatacenterId || datacenterId < 0)

{

throw new ArgumentException(string.Format("datacenter Id can't be greater than {0} or less than 0", maxDatacenterId));

}

this.workerId = workerId;

this.datacenterId = datacenterId;

}

public long NextId()

{

long timestamp = TimeGen();

if (timestamp < lastTimestamp)

{

throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp));

}

if (lastTimestamp == timestamp)

{

sequence = (sequence + 1) & sequenceMask;

if (sequence == 0)

{

timestamp = TilNextMillis(lastTimestamp);

}

}

else

{

sequence = 0L;

}

lastTimestamp = timestamp;

return ((timestamp - epoch) << timestampLeftShift) |

(datacenterId << datacenterIdShift) |

(workerId << workerIdShift) |

sequence;

}

protected long TilNextMillis(long lastTimestamp)

{

long timestamp = TimeGen();

while (timestamp <= lastTimestamp)

{

timestamp = TimeGen();

}

return timestamp;

}

protected long TimeGen()

{

return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;

}

}

在这个例子中,SnowflakeIdGenerator 类封装了生成雪花主键的逻辑。构造函数接受机器IDworkerId)和数据中心IDdatacenterId)作为参数,这些ID在分布式系统中应该是唯一的。NextId 方法是生成新ID的入口点。它首先检查当前时间戳是否小于上一次生成ID的时间戳,如果是,则抛出一个异常。然后,根据时间戳是否相同来递增序列或等待下一个毫秒。最后,通过位运算组合时间戳、数据中心ID、机器ID和序列来生成最终的雪花主键。

Entity Framework (EF) 中使用雪花主键生成器,你需要将生成的雪花ID作为实体的主键值。这通常涉及到几个步骤:

  1. 定义实体类,并在其中指定主键属性。
  2. 在DbContext中配置实体,以便EF知道如何使用雪花主键生成器。
  3. 在应用程序启动时初始化雪花主键生成器,并将其注入到需要它的服务中。

下面是一个简单的示例,展示如何在EF Core中使用雪花主键生成器:

首先,定义你的实体类,并指定主键属性:

csharp代码

public class MyEntity

{

public long SnowflakeId { get; set; } // 这是雪花主键

// 其他属性...

}

然后,在DbContext中配置实体,使用HasDefaultValueSql方法来指定在插入新记录时如何生成雪花ID

csharp代码

public class MyDbContext : DbContext

{

public DbSet<MyEntity> MyEntities { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)

{

modelBuilder.Entity<MyEntity>()

.HasKey(e => e.SnowflakeId) // 设置SnowflakeId为主键

.ForSqlServerHasDefaultValueSql("DEFAULT(NEXT VALUE FOR SnowflakeSequence)"); // 使用SQL Server的序列

// 其他配置...

}

}

请注意,上面的代码使用了ForSqlServerHasDefaultValueSql方法,这是针对SQL Server数据库的。如果你使用的是其他数据库提供程序,你需要使用相应的方法来配置默认值。

接下来,你需要创建一个雪花ID序列,以便数据库可以生成ID。这通常在数据库迁移脚本中完成。以下是一个SQL Server的示例:

sql代码

CREATE SEQUENCE SnowflakeSequence

AS BIGINT

START WITH 1

INCREMENT BY 1;

然后,在应用程序启动时(例如在Startup.csProgram.cs中),你需要初始化雪花主键生成器,并将其注入到EF Core的上下文中。这可以通过依赖注入来实现:

csharp代码

public void ConfigureServices(IServiceCollection services)

{

// ... 其他服务配置 ...

// 配置雪花主键生成器

services.AddSingleton<ISnowflakeIdGenerator, SnowflakeIdGenerator>(serviceProvider =>

{

// 获取配置的服务,例如应用程序设置或配置文件中的workerId和datacenterId

var workerId = // 从配置中获取workerId;

var datacenterId = // 从配置中获取datacenterId;

return new SnowflakeIdGenerator(workerId, datacenterId);

});

// 添加DbContext,并配置依赖注入

services.AddDbContext<MyDbContext>(options =>

{

// 从依赖注入容器中获取雪花主键生成器

var snowflakeIdGenerator = serviceProvider.GetService<ISnowflakeIdGenerator>();

// 配置DbContext使用雪花主键生成器

options.UseSqlServer(yourConnectionString, sqlServerOptionsAction: sqlOptions =>

{

// 配置其他SQL Server选项...

})

.EnableSensitiveDataLogging(true) // 根据需要启用或禁用

.UseInternalServiceProvider(serviceProvider); // 使用内部服务提供者来解析依赖项

});

// ... 其他服务配置 ...

}

在这个例子中,ISnowflakeIdGenerator是一个接口,它定义了生成雪花ID的方法。你可以根据你的需要实现这个接口,并在依赖注入容器中注册实现。然后,在配置DbContext时,你可以从服务提供者中获取这个实现,并使用它来配置如何生成主键。

请注意,这个方法将雪花ID的生成逻辑从EF Core中分离出来,允许你更容易地测试和替换主键生成策略。此外,这种方法还允许你在不使用EF Core的情况下生成雪花ID,例如在需要手动插入记录到数据库的场景中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/679700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

接口测试框架分析

框架大体上已经写完了&#xff0c;不过说实话好多代码让我自己写我也写不出来&#xff0c;那该怎么办呢&#xff1f;很简单&#xff0c;把现在已经写好的代码保存起来&#xff0c;等用的时候拿出来复制粘贴就好了&#xff0c;如果你是大神&#xff0c;自己会写&#xff0c;那就…

TikTok:短视频时代的崛起

导言&#xff1a; TikTok&#xff0c;作为一款全球短视频社交应用&#xff0c;正风靡全球&#xff0c;引领着数字娱乐的新潮流。其简洁的用户界面、创意无限的短视频内容&#xff0c;以及强大的社交互动功能&#xff0c;使其成为全球数以亿计的用户喜爱的平台。 TikTok的特点&a…

H5 红色文字抖动网址发布页/引导页源码

H5 红色文字抖动网址发布页/引导页源码 源码介绍&#xff1a;一款红色文字抖动网页源码&#xff0c;可用于引导页或网址发布页。 下载地址&#xff1a; https://www.changyouzuhao.cn/10470.html

第9讲用户信息修改实现

用户信息修改实现 后端修改用户昵称&#xff1a; /*** 更新用户昵称* param wxUserInfo* param token* return*/ RequestMapping("/updateNickName") public R updateNickName(RequestBody WxUserInfo wxUserInfo,RequestHeader String token){if(StringUtil.isNot…

在JavaScript或TypeScript中,@符号的用法

在JavaScript或TypeScript中&#xff0c;符号在导入语句中用作包名的一部分&#xff0c;表示该包是一个命名空间包&#xff08;Namespace package&#xff09;或作用域包&#xff08;Scoped package&#xff09;。这种命名方式主要用于组织和管理由同一组织或个人发布的相关包。…

MySQL篇----第二十二篇

系列文章目录 文章目录 系列文章目录前言一、什么是表级锁二、什么是页级锁三、什么是行级锁四、什么是悲观锁前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、…

selenium 驱动 Edge浏览器,解决selenium打开Edge浏览器闪退问题

一、Edge浏览器驱动下载 1、在设置中查看浏览器的版本号 2、在官网中进行对应下载 Microsoft Edge WebDriver - Microsoft Edge Developer 二、环境变量配置 1、打开设置界面 右击【此电脑】---选择【属性】----选择【高级系统设置】-----点击【环境变量】 2、变量设置 在…

SpringCloud-项目引入Nacos

一、安装Nacos服务 首先&#xff0c;我们需要从 Nacos 的官方网站下载发布版本。下载地址&#xff1a;Releases alibaba/nacos GitHub 选择合适的版本并下载&#xff0c;解压缩得到 Nacos 的安装包。 在解压后的 Nacos 目录中&#xff0c;找到 bin 文件夹。 用写字板编辑…

Git 为 ssh 协议设置代理

前言 我们为终端设置clash代理的时候,一般都是设置的http/https或者socks.但是我们用github的时候一般是用密钥也就是ssh链接. 教程 在~/.ssh/config文件中加入以下的代码. Host github.comHostname ssh.github.comPort 443User gitProxyCommand nc -v -x 172.28.208.1:789…

【玩转408数据结构】线性表——线性表的顺序表示(顺序表)

知识回顾 通过前文&#xff0c;我们了解到线性表是具有相同数据类型的有限个数据元素序列&#xff1b;并且&#xff0c;线性表只是一种逻辑结构&#xff0c;其不同存储形式所展现出的也略有不同&#xff0c;那么今天我们来了解一下线性表的顺序存储——顺序表。 顺序表的定义 …

【ES6】模块化

nodejs遵循了CommonJs的模块化规范 导入 require() 导出 module.exports 模块化的好处&#xff1a; 模块化可以避免命名冲突的问题大家都遵循同样的模块化写代码&#xff0c;降低了沟通的成本&#xff0c;极大方便了各个模块之间的相互调用需要啥模块&#xff0c;调用就行 …

在centos中安装chrome,为selenium做准备

一、安装chrome浏览器 1.系统需求 CentOS 7 系统必须是 64 位系统&#xff0c;Chrome 没有 32 位系统的软件包。 2.在 CentOS 7 系统中添加谷歌官方 Yum 软件源 在 CentOS 7 系统下的 /etc/yum.repos.d/ 文件夹中创建 google-chrome.repo 文件&#xff1a; sudo vi /et…

力扣_字符串6—最小覆盖字串

题目 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 “” 。 示例 &#xff1a; 输入&#xff1a;s “ADOBECODEBANC”, t “ABC” 输出&#xff1a;“BANC” 解释&#xff1a;…

安装faiss环境教程

文章目录 打开环境安装faiss环境检查已安装的环境切换环境至faiss 打开环境 source activate # 打开环境安装faiss环境 conda create -n faiss_env # 安装faiss环境检查已安装的环境 conda info --envs # 检查已安装的环境切换环境至faiss conda a…

MySQL数据库⑧_索引(概念+理解+操作)

目录 1. 索引的概念和价值 1.1 索引的概念 1.2 索引的价值 2. 磁盘的概念 2.1 磁盘的结构 2.2 操作系统与磁盘交互的基本单位 2.3 MySQL与磁盘交互的基本单位 3. 索引的理解 3.1 主键索引现象和推导 3.2 索引采用的数据结构&#xff1a;B树 3.3 聚簇索引和非聚簇索引…

关于物理机ping不通虚拟机问题

方法一 设置虚拟机处于桥接状态即可&#xff1a;&#xff08;虚拟机->设置->网络适配器&#xff09;&#xff0c;选择完确定&#xff0c;重启虚拟机即可。 方法二 如果以上配置还是无法ping通&#xff1a;&#xff08;编辑->虚拟网络编辑器&#xff09; 首先查看主机网…

spring mvc和 spring boot 以及 spring cloud的区别

Spring MVC Spring MVC是Spring框架中的一个模块&#xff0c;专门用于构建Web应用程序的控制器层。它基于MVC&#xff08;Model-View-Controller&#xff09;设计模式&#xff0c;实现了Web层的请求处理、数据绑定和视图渲染等功能。 特点&#xff1a; 请求驱动&#xff1a;S…

###C语言程序设计-----C语言学习(12)#进制间转换,十进制,二进制,八进制,十六进制

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 计算机处理的所有信息都以二进制形式表示&#xff0c;即数据的存储和计算都采…

containerd中文翻译系列(二十二)运行时v2

Runtime v2 为运行时作者集成 containerd 引入了一级 shim API。 containerd 作为守护进程&#xff0c;并不直接启动容器。相反&#xff0c;它充当更高级别的管理器 或枢纽的作用&#xff0c;以协调容器和内容的活动。被称作 "运行时"的程序真正来启动、停止和管理容…