强类型ID

实体通常是整数,GUID或者string类型,因为数据库直接支持这些类型,但是,如果实体的ID的类型是一样的,比如都是整数的ID,这有可能会出现ID值传错的问题,看下边的示例。

public void AddProductToOrder(int orderId, int productId, int count)
{
...
} ... // 这个地方,参数传错了
AddProductToOrder(productId, orderId, int count);

上面的代码可以很好地通过检查并编译,但是在运行的时候就出问题了,这是逻辑bug。

幸运的是,可以定义强类型id来解决这个问题,这个想法很简单,为每个实体的ID声明一个特定的类型,现在需要这样写:

// 使用强类型ID代替整数ID
public void AddProductToOrder(OrderId orderId, ProductId productId, int count)
{
...
} ... // 这个地方,参数传错了
AddProductToOrder(productId, orderId, int count);

在上面的代码中,我们犯了与第一个示例相同的错误(交换productId和orderId),但是在这种情况下,类型不同,因此编译器会捕获该错误并报告错误,我们仍然需要对其进行修复,但是至少在生产中并没有爆炸。

编写一个强类型的id

public readonly struct ProductId : IEquatable<ProductId>
{
public ProductId(int value)
{
Value = value;
} public int Value { get; } public bool Equals(ProductId other) => other.Value == Value;
public override bool Equals(object obj) => obj is ProductId other && Equals(other);
public override int GetHashCode() => Value.GetHashCode();
public override string ToString() => $"ProductId {Value}";
public static bool operator ==(ProductId a, ProductId b) => a.Equals(b);
public static bool operator !=(ProductId a, ProductId b) => !a.Equals(b);
}

上面的代码没什么难的,但是如果每个实体都需要的话,那确实有点麻烦,在C# 9 可以使用source generators来完成这些,但是C# 9还引入了另一个功能,使用起来更方便。

Record类型

Record 类型是具有内置不变性和值语义的引用类型,它和上面我们写的强类型是一样的(手动写的成员实现Equals,GetHashCode等等),在代码中使用也非常简洁, 如果我们ProductId使用record重写类型,就是下边这样:

public record ProductId(int Value);

是的,您没看错,这是一行,而上面的代码是一大段,它完成了我们手动执行的所有操作(实际上,还多了很多!)。

主要区别在于:我们的手动实现是struct,即值类型,但是记录是引用类型,这意味着它们可以为null,这可能不是主要问题,尤其是在使用可为空的引用类型的情况下,但是要知道这一点。

现在为模型中的每个实体编写一个强类型的id是不是很简单,使用Record 非常方便,当然,还有其他问题需要考虑,例如JSON序列化,与Entity Framework Core一起使用等,但这是另一篇文章的故事!

最后

欢迎扫码关注我们的公众号 【全球技术精选】,专注国外优秀博客的翻译和开源项目分享,也可以添加QQ群 897216102

最新文章

  1. H3 BPM初次安装常见错误详解5-7
  2. 实现滑动可固定header以及页面刷新
  3. STL之关联容器
  4. Elasticsearch配置文件说明
  5. springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序
  6. apache ab压力测试
  7. js根据className获取元素封装
  8. php5.4.3连接SQLite3
  9. LR脚本技巧
  10. 每天一个Linux命令(2): ls
  11. Android ndk下用AssetManager读取assets的资源
  12. 一款基于jquery的下拉点击改变背景图片
  13. ES6:JavaScript 新特性
  14. Android知识简单测试题
  15. FineUI开发一个b/s结构
  16. python的with语句,超级强大
  17. Webpack 2 视频教程 011 - Webpack2 中加载 CSS 的相关配置与实战
  18. ionic2 获取dom节点
  19. webpack多页面配置
  20. Spring AOP的实现及源码解析

热门文章

  1. 题解-MtOI2019 幽灵乐团
  2. 题解-The Number of Good Intervals
  3. 数据结构—— Trie (前缀树)
  4. js生成随机数、随机数列、数值转金融格式
  5. C 与 C++ 中 指向二维数组的指针进行指针运算
  6. Windows单机安装hadoop
  7. 多任务-python实现-Thread的基本使用(2.1.1)
  8. Yii 文件上传类的使用
  9. gcc编译阶段打印宏定义的内容
  10. HCIP --- BGP实验