惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
V
Vulnerabilities – Threatpost
Security Latest
Security Latest
AI
AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
量子位
H
Help Net Security
Attack and Defense Labs
Attack and Defense Labs
The GitHub Blog
The GitHub Blog
L
LINUX DO - 最新话题
A
Arctic Wolf
博客园_首页
S
Securelist
S
Secure Thoughts
Google DeepMind News
Google DeepMind News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
N
Netflix TechBlog - Medium
Cyberwarzone
Cyberwarzone
小众软件
小众软件
T
Threatpost
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Blog — PlanetScale
Blog — PlanetScale
N
News and Events Feed by Topic
NISL@THU
NISL@THU
Forbes - Security
Forbes - Security
博客园 - 聂微东
F
Fortinet All Blogs
Simon Willison's Weblog
Simon Willison's Weblog
H
Heimdal Security Blog
罗磊的独立博客
S
Security @ Cisco Blogs
B
Blog
T
Troy Hunt's Blog
Engineering at Meta
Engineering at Meta
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Hacker News
The Hacker News
The Last Watchdog
The Last Watchdog
Hacker News - Newest:
Hacker News - Newest: "LLM"
I
Intezer
T
Threat Research - Cisco Blogs
C
Cybersecurity and Infrastructure Security Agency CISA
The Cloudflare Blog
S
Schneier on Security
月光博客
月光博客
L
LINUX DO - 热门话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org

元视角

.NET 生态下的 Agent 框架选型:从 ReAct 到原生推理 - 元视角 从「能用」到「好用」:LLM 流式响应实现方式的探索之路 - 元视角 当我用 2000 条聊天记录,让 AI 为我画一幅自画像 - 元视角 基于 Supabase 的 AI 应用开发探索 - 元视角 微博 × MCP:社交媒体新玩法解锁 - 元视角 四点钟海棠花未眠 - 元视角 Semantic Kernel × MCP:智能体的上下文增强探索 - 元视角 基于 K-Means 聚类分析实现人脸照片的快速分类 - 元视角 容器技术驱动下的代码沙箱实践与思考 - 元视角 温故而知新:后端通用查询方案的再思考 - 元视角 浅议 CancellationToken 在前后端协同取消场景中的应用 - 元视角 Semantic Kernel 视角下的 Text2SQL 实践与思考 - 元视角 关于 ChatGPT 的流式传输,你需要知道的一切 - 元视角 RAG 的是与非、Rewrite 和 Rerank - 元视角 使用 EFCore 和 PostgreSQL 实现向量存储及检索 - 元视角 基于 LLaMA 和 LangChain 实践本地 AI 知识库 - 元视角 使用 llama.cpp 在本地部署 AI 大模型的一次尝试 - 元视角 如何为 Git 配置多个 SSH Key - 元视角 C# 使用 LibUsbDotNet 实现 USB 设备检测 - 元视角 基于 C# 实现样式与数据分离的打印方案 - 元视角 基于 SVG 的图形交互方案实践 - 元视角 前端视频播放技术概览 - 元视角 温故而知新,再话 Python 动态导入 - 元视角 后 GPT 时代,NLP 不存在了? - 元视角 视频是不能 P 的系列:使用 Milvus 实现海量人脸快速检索 - 元视角 GDI+下字体大小自适应方案初探 - 元视角 小爱音箱集成 ChatGPT 的不完全教程 - 元视角 程序员视角下的三体世界随想 - 元视角 关于 Docker 容器配置信息的渐进式思考 - 元视角 在 Docker 容器内集成 Crontab 定时任务 - 元视角 为你的服务器集成 LDAP 认证 - 元视角 似花还似非花 - 元视角 视频是不能 P 的系列:使用 Dlib 实现人脸识别 - 元视角 浅议分布式链路追踪与日志的整合 - 元视角 关于 Git 大文件上传这件小事 - 元视角 .NET 进程内队列 Channel 的入门与应用 - 元视角 使用 Fody 实现 .NET 的静态编织 - 元视角 .NET Core + ELK 搭建可视化日志分析平台(下) - 元视角 聊一聊前端图片懒加载背后的故事 - 元视角 支持外部链接跳转的 Vue Router 扩展实现 - 元视角 视频是不能 P 的系列:OpenCV 和 Dlib 实现表情包 - 元视角 不得不说的 ASP.NET Core 集成测试 - 元视角 再议 DDD 视角下的 EFCore 与 领域事件 - 元视角 Vue.js 前端项目容器化部署实践极简教程 - 元视角 再见,人间四月天 - 元视角 Python 图像风格化迁移助力画家梦想 - 元视角 利用 ASP.NET Core 中的标头传播实现分布式链路追踪 - 元视角 利用 gRPC 实现文件的上传与下载 - 元视角 七种武器:延迟队列的原理和实现总结 - 元视角 gRPC 流式传输极简入门指南 - 元视角 Envoy 集成 Jaeger 实现分布式链路追踪 - 元视角 浅议非典型 Web 应用场景下的身份认证 - 元视角 gRPC 借助 Any 类型实现接口的泛化调用 - 元视角 分布式丛林探险系列之 Redis 集群模式 - 元视角 分布式丛林探险系列之 Redis 主从复制模式 - 元视角 通过 Python 预测 2021 年双十一交易额 - 元视角 gRPC 搭配 Swagger 实现微服务文档化 - 元视角 SSL/TLS 加密传输与数字证书的前世今生 - 元视角 使用 Python 自动识别防疫健康码 - 元视角 你不可不知的容器编排进阶技巧 - 元视角 ASP.NET Core 搭载 Envoy 实现 gRPC 服务代理 - 元视角 再话 AOP,从简化缓存操作说起 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务身份认证(JWT) - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的监控预警 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的反向代理 - 元视角 ASP.NET Core gRPC 打通前端世界的尝试 - 元视角 ASP.NET Core gRPC 集成 Polly 实现优雅重试 - 元视角 ASP.NET Core gRPC 健康检查的探索与实现 - 元视角 ASP.NET Core gRPC 拦截器的使用技巧分享 - 元视角 SnowNLP 使用自定义语料进行模型训练 - 元视角 使用 HttpMessageHandler 实现 HttpClient 请求管道自定义 - 元视角 ABP vNext 的实体与服务扩展技巧分享 - 元视角 ABP vNext 对接 Ant Design Vue 实现分页查询 - 元视角 源代码探案系列之 .NET Core 跨域中间件 CORS - 元视角 源代码探案系列之 .NET Core 限流中间件 AspNetCoreRateLimit - 元视角 源代码探案系列之 .NET Core 并发限制中间件 ConcurrencyLimiter - 元视角 通过 EmbededFileProvider 实现 Blazor 的静态文件访问 - 元视角 低代码,想说爱你不容易 - 元视角 记一次失败的 ThoughtWorks 面试经历 - 元视角 从 C# 1.0 到 C# 9.0,历代 C# 语言特性一览 - 元视角 通过 Python 分析 2020 年全年微博热搜数据 - 元视角 基于 Python 和 Selenium 实现 CSDN 一键三连自动化 - 元视角 使用多线程为你的 Python 爬虫提速的 N 种姿势,你会几种? - 元视角 实现网页长截图的常见思路总结 - 元视角 温故而知新,由 ADO.NET 与 Dapper 所联想到的 - 元视角 视频是不能 P 的系列:OpenCV 人脸检测 - 元视角 作为技术宅的我,是这样追鬼滅の刃的 - 元视角 使用 Python 抽取《半泽直树》原著小说人物关系 - 元视角 厉害了!打工人用 Python 分析西安市职位信息 - 元视角 使用 dotTrace 对 .NET 应用进行性能分析与优化 - 元视角 一道 HashSet 面试题引发的蝴蝶效应 - 元视角 基于选项模式实现.NET Core 的配置热更新 - 元视角 Dapper.Contrib 在 Oracle 环境下引发 ORA-00928 异常问题的解决 - 元视角 .NET Core 中对象池(Object Pool)的使用 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(下):EventBus 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(中):RabbitMQ 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(上):基础篇 - 元视角 记一次从已损坏的 Git 仓库中找回代码的经历 - 元视角 .NET Core 原生 DI 扩展之属性注入实现 - 元视角 .NET Core 原生 DI 扩展之基于名称的注入实现 - 元视角
EFCore 实体命名约定库:EFCore.NamingConventions - 元视角
飞鸿踏雪 · 2021-06-18 · via 元视角

在软件开发过程中,数据库永远都是绕不开的一个话题。有时候,我们甚至会因此而获得一个名字——“CURD Boy”。虽然不过是朴实无华的“增删查改”,可隐隐然早已分出了无数的流派。在这些不同的流派中,有的人坚持“我手写我心”,认为手写SQL才是真正的王道,没有读过/写过成百上千行的存储过程,便不足以谈论程序员的人生。而有的人喜欢ORM的清晰、整洁,认为数据库和面向对象存在着天然抗阻,ORM更有利于推进DDD和微服务的落地。相信大家都听说过Java里的SSH框架,从HibernateMybatis再到Spring Data JPA,可以说这种争论一直没有停止过。这里我们不打算讨论这个问题,我们平时使用EF或者EFCore的过程中,作为连接数据库和面向对象两个异世界的桥梁,ORM需要我们来告诉它,实体数据与数据库表字段的映射关系,所以,经常需要通过数据注解或者Fulent API来写各种配置。那么,有没有什么方案可以让我们偷这个懒呢?下面隆重请出本文的主角:EFCore.NamingConventions

使用方法

EFCore. NamingConventions,目前由一个非官方的组织进行维护,代码托管在 Github 上,100%的开源项目。

如果你希望直接使用它的话,可以直接通过NuGet进行安装:

Install-Package EFCore.NamingConventions  

接下来,我们只需要在DbContextOnConfiguring()方法中,调用它提供的扩展方法即可:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)  
=> optionsBuilder  
.UseSqlite("Data Source=Chinook.db")
.UseSnakeCaseNamingConvention();  

或者,你可以使用依赖注入的方式:

services.AddDbContext<ChinookContext>(options => 
    options.UseSqlite("Data Source=Chinook.db")
          .UseSnakeCaseNamingConvention()
);

这里我以SQLite数据库为例,来展示它的具体使用细节。事实上,它提供了 4 种命名约定的策略:

  • UseSnakeCaseNamingConvention: FullName -> full_name
  • UseLowerCaseNamingConvention: FullName -> fullname
  • UseCamelCaseNamingConvention: FullName -> fullName
  • UseUpperCaseNamingConvention: FullName -> FULLNAME

简单来说,就是当我们的实体中存在一个属性FullName时,它会告诉EF或者EFCore,这个属性FullName对应的表字段是什么。

虽然,在大多数的场景中,我们都希望属性名称和表字段一致,可你要知道,像Oracle这种对大小写敏感的数据库,特别喜欢自作聪明地帮你全部改成大写。

所以,在上家公司工作的时候,为了兼容Oracle这病态的癖好,公司里有个不成文的规定,那就是:所有实体的属性名称最好都大写。

本来大家用驼峰命名就是为了好认单词,好家伙!这下全部大写了,一眼望过去简直就是灾难,因为没有办法做到“望文生义”,如果那个时候知道这个库的存在,是不是就能解决这个问题了呢?

第一个示例

下面我们以UseSnakeCaseNamingConvention为例,结合SQLite来做一个简单的例子。

首先,我们定义必要的实体,并为DbContext配置实体命名约束规则:

// Album
public class Album
{
    public int AlbumId { get; set; }
    public string Title { get; set; }
    public int ArtistId { get; set; }
    public string TenantId { get; set; }
}

// Artist
public class Artist
{
    public int ArtistId { get; set; }
    public string Name { get; set; }
    public string TenantId { get; set; }
}

接下来,通过迁移命令来生成数据库架构:

Add-Migration "Init-Database" -Context ChinookContext
Update-Database

可以注意到,生成的数据库表字段会以小写+下划线的方式命名。这就是所谓的实体命名约束。

通过实体命名约束生成的 Album 表 通过实体命名约束生成的 Album 表

只要大家都看着这个约定来写实体的属性,这套机制就可以完美工作。它和MVC里的默认路由一样,都是属于一种“约定大于配置”的方案。

在我看来,不管是配置还是约定。当以团队为单位进行协作时,最好还是以文档的形式记录下来,否则会出现两种结局,其一是没人知道怎么配置,其二是新人不知道有这个约定

以上就是EFCore.NamingConventions的基本用法,更多的细节大家可以去阅读它的README,因为这个库需要结合迁移功能来使用,所以,如果要在已存在的表上应用这套约束规则时,建议大家还是小心谨慎一点。

我个人觉得,它可以方便团队去制定一套数据库规范,进而去约束开发人员写出更规范的命名。

本文小结

本文主要介绍了可用于EFCore的实体命名约束库:EFCore.NamingConventions。这是一个由社区维护的、开源的项目,它可以在创建DbContext的时候,指定一个实体命名约束规则,即实体属性如何与数据库表字段进行对应,这是一种约定大于配置的方案,一旦团队形成了属于自己的数据库命名风格,那么,研发人员只需要按照规范为实体属性命名,例如开发人员可以使用驼峰风格的命名,而数据库管理员则可以使用下划线风格的命名。这样,就可以省略一部分字段映射的配置代码,从而提高团队研发的效率。值得说明的一点是,不管是配置还是约定。当以团队为单位进行协作时,最好还是以文档的形式记录下来,否则会出现两种结局,其一是没人知道怎么配置,其二是新人不知道有这个约定。好了,以上就是这篇博客的全部内容啦,谢谢大家!