领域驱动设计自动递增实体键

问题描述 投票:0回答:3

刚开始领域驱动设计,我了解到您应该使模型保持有效状态,并且在创建类的新实例时,建议将所有必需的属性作为构造函数参数。

但是,当使用自动递增键时,当我从持久层调用 Add 方法时,我只会获得这个新 ID。如果我在没有密钥的情况下实例化我的对象,我认为它们将处于无效状态,因为它们需要某种唯一标识符。

我应该如何实现我的架构,以便在创建实体的新实例之前获得我的 ID?

entity domain-driven-design auto-increment
3个回答
14
投票

生成的随机 ID

这里的实用方法是使用随机ID并在实例化实体之前生成它们,例如在一家工厂里。 GUID 是常见的选择。

在您提问之前:不,您不会用完 GUID :-)

带 ID 预留的连续 ID

如果由于某种原因必须使用顺序 ID,那么您仍然有选择:

  • 查询数据库上的序列以获得下一个ID。这取决于您的数据库产品,例如 Oracle 有它们)。
  • 创建一个带有自动增量键的表,仅用作键保留表。要获取 ID,请在该表中插入一行 - 生成的键现在已为您保留,因此您可以将其用作实体的 ID。

请注意,这两种顺序 ID 方法都需要在开始创建实体之前进行数据库往返。这就是随机 ID 通常更简单的原因。因此,如果可以的话,请使用随机 ID。

数据库生成的 ID

另一种可能性是接受这样一个事实:您在创建时没有 ID,但只有在数据库上的插入操作成功时才具有 ID。根据我的经验,这会使实体创建难以使用,因此我避免使用它。但对于非常简单的情况,这可能是一种有效的方法。


0
投票

除了 Dmi 的评论

1)您可以在工厂方法中确保您的实体存储到数据库中。这可能适用于您的域,也可能不适用于您的域,但如果您确定将保存该实体,这可能是一种有效的方法

2)您可以将ID与主键从数据库中分离出来。我曾经处理过一个案例,如果客户付款,那么某些东西只是一个订单,此时它将通过其发票 ID(顺序 ID)进行识别。这并不意味着在数据库中我需要一个列 ID,它也是对象的主键。您可以在数据库中拥有一个主键(随机 guid),并拥有一个连续的 ID(int?),如果尚未填充,则为 null。


0
投票

嗯,我通常这样使用它:

我有一个可变的值对象 ID:

// Value Object id.ts
import IValueObject from "@shared/domain/implementation/IValueObject";
import CustomError from "../service/custom-error";

export default class Id implements IValueObject<Id> {
    constructor(private id: string) {
        this.id = String(id)
        if (!id) throw new Error('ID not provided');
    }

    value() {
        return this.id
    }

    equals(vo: Id): Boolean {
        return this.value() === vo.value()
    }

    compare(id: string) {
        return this.equals(new Id(id))
    }

    static generate(): string {
        return 'temp_' + Math.random().toString(36).substring(2);
    }

    isGenerated() {
        return this.id.startsWith('temp_');
    }

    setRealId(id: string) {
        if (this.isGenerated()) {
            this.id = String(id);
        } else {
            throw new CustomError("ID has already been set and cannot be changed.", 'implementation failure');
        }
    }

    static build(id: string | Id){
        if(id instanceof Id) return id;
        return new Id(id)
    }
}

在我的实体中,我有一个 create 方法来创建一个新数据的实体实例,因此,在 create 方法中,我使用 Id.generate() 创建我的 id,并在存储库上的 save 方法中,我调用实体方法 setId ,要设置自动递增id,它会替换随机id,如下所示:

setId(id: 字符串){ this.Id.setRealId(id) 返回这个 }

它们、与我的实体 ID 相关的所有其他实体和聚合根也将被替换,因为具有相同的实例。

© www.soinside.com 2019 - 2024. All rights reserved.