如何在我的业务逻辑层中管理单一性?
How to manage unicity in my buisness logic layer?
在 aspnetcore mvc 执行上下文中。
我有这个简单的实体。
public class Foo
{
public int Id { get; private set; }
public string Name{ get; private set; }
public string Code { get; private set; }
private Foo() { }
public Foo(string Name, string Code)
{
GuardClauses.IsNullOrWhiteSpace(Name,nameof(Name), "cannot be null or empty");
GuardClauses.IsNullOrWhiteSpace(Code, nameof(Code), "cannot be null or empty");
this.Nom = Nom;
this.Code = Code;
}
}
在我的 DbContext 中,我有这段代码 field/constraint 确保代码从持久性的角度来看是唯一的。
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Foo>()
.HasIndex(u => u.Code)
.IsUnique();
}
我希望我的服务中的 addNewFoo 方法 class 确保对于我的应用程序中的所有 Foos,属性 代码在添加它之前是唯一的。
我尽我所能尊重坚持无知原则,但我没有像我希望的那样熟练。
对于初学者来说,确定代码字段是否唯一是构建者的角色吗?
其次,我知道在我的验证层中,我可以确定是否已经存在与我当前尝试添加的实际 foo 具有相同代码的现有 foo。但是这个方法不是线程安全的或事务性的。
事实是我不想等到我添加我的 foo 时也有一个 SqlException,只是为了知道它不能完成。
确保我的应用程序唯一性的最佳方法是什么
牢记 Fail Fast 原则。
因为没有系统的具体示例或描述,所以我将概括一下。如果您提供一个具体示例,我可以添加其他信息。每个解决方案都有一个上下文,它最适用于该解决方案,当然总是要权衡取舍
让我们问几个关于这个代码的性质及其代表的问题
谁负责代码生成:系统的用户或系统本身?
代码能否完全随机(例如UUID)?
是某种特殊算法生成的代码(SSN or maybe a CarPartNumber由具有特殊含义的不同部分组成)
还有一个非常重要的问题:
- 我们预计这些独特的违规行为会多久发生一次?
如果问题 2 的答案是肯定的,那么您就没有问题。您可以拥有重复的 UUID,但几率非常低。您可以向数据库添加 Unique Constrant 以防万一,并将此违规视为您不关心的正常错误,因为它每百万年就会发生一次。
如果问题3的答案是肯定的,那么我们的情况就不同了。在多用户系统中,您无法避免并发。有几种方法可以处理这种情况:
选项 3:如果 系统 正在生成代码,有一个特殊的服务和队列代码生成请求。
如果您选择使用锁,您可以锁定整个资源 Foo 或仅锁定 Code 代。
选项 1:
您将不得不处理 SQLException。今天在大多数应用程序中都使用这个,因为它不会因为有人锁定资源而导致应用程序长时间停顿,从而确保流畅的 用户体验。
您可以使用抽象,例如存储库。定义您自己的应用程序级异常 UniqueCodeViolationException,该异常将由存储库抛出。存储库将尝试{}捕获{} SQLException、处理它并在比较错误代码时将其包装在 UniqueCodeViolationException 中。这不会为您节省检查时间,但至少会隐藏具体错误,并且您只会在一个地方进行处理。
选项 2:
有时候确实需要保证没有并发,所以就用这个选项。在这种情况下,您将不得不为一个用户锁定创建 Foo 的过程,并且不允许其他人甚至能够打开 dialog/form/page如果有锁,则创建 Foo。
这确保了一致性,并通过创建一个基本上无法用于多个目标相同 Foo 的用户的系统来避免问题。您正在构建的应用程序很可能只有一个人负责创建 Foo 或者并发性很低,因此这可能是一个很好的解决方案。
我有朋友在保险的申请中使用这把锁。通常在他们的申请中,一个人会去一个办公室办理一份保险。所以同时为同一个人创建一份保险的可能性很低,但是为同一个人创建多份保险的成本是非常高的。
选项 3:
另一方面,如果您的代码是由 System 生成的,您可以使用 CodeGenerationService 来处理代码生成并确保生成唯一代码。您可以对这些请求进行排队。在服务中的每个生成操作中,您可以检查此代码是否存在以及 return 错误(或抛出异常)。
现在提问4。如果您不希望经常发生冲突,只需在您的数据库中添加一个 Unique Constraint 并将其视为一般意外错误。添加检查 Code 是否已经存在,如果存在则显示错误。
您仍然可以在这里进行并发,因此会有一个微小的变化,即一个用户将添加一个 Foo,而另一个用户将得到一个错误 "Oooops... something whent wrong.. please try again"。因为这将在 100 年内发生一次,所以没关系。
最后一个解决方案将忽略在极少数情况下可能发生的特殊情况,从而使您的系统更加简单。
在 aspnetcore mvc 执行上下文中。
我有这个简单的实体。
public class Foo
{
public int Id { get; private set; }
public string Name{ get; private set; }
public string Code { get; private set; }
private Foo() { }
public Foo(string Name, string Code)
{
GuardClauses.IsNullOrWhiteSpace(Name,nameof(Name), "cannot be null or empty");
GuardClauses.IsNullOrWhiteSpace(Code, nameof(Code), "cannot be null or empty");
this.Nom = Nom;
this.Code = Code;
}
}
在我的 DbContext 中,我有这段代码 field/constraint 确保代码从持久性的角度来看是唯一的。
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Foo>()
.HasIndex(u => u.Code)
.IsUnique();
}
我希望我的服务中的 addNewFoo 方法 class 确保对于我的应用程序中的所有 Foos,属性 代码在添加它之前是唯一的。
我尽我所能尊重坚持无知原则,但我没有像我希望的那样熟练。
对于初学者来说,确定代码字段是否唯一是构建者的角色吗?
其次,我知道在我的验证层中,我可以确定是否已经存在与我当前尝试添加的实际 foo 具有相同代码的现有 foo。但是这个方法不是线程安全的或事务性的。
事实是我不想等到我添加我的 foo 时也有一个 SqlException,只是为了知道它不能完成。
确保我的应用程序唯一性的最佳方法是什么 牢记 Fail Fast 原则。
因为没有系统的具体示例或描述,所以我将概括一下。如果您提供一个具体示例,我可以添加其他信息。每个解决方案都有一个上下文,它最适用于该解决方案,当然总是要权衡取舍
让我们问几个关于这个代码的性质及其代表的问题
谁负责代码生成:系统的用户或系统本身?
代码能否完全随机(例如UUID)?
是某种特殊算法生成的代码(SSN or maybe a CarPartNumber由具有特殊含义的不同部分组成)
还有一个非常重要的问题:
- 我们预计这些独特的违规行为会多久发生一次?
如果问题 2 的答案是肯定的,那么您就没有问题。您可以拥有重复的 UUID,但几率非常低。您可以向数据库添加 Unique Constrant 以防万一,并将此违规视为您不关心的正常错误,因为它每百万年就会发生一次。
如果问题3的答案是肯定的,那么我们的情况就不同了。在多用户系统中,您无法避免并发。有几种方法可以处理这种情况:
选项 3:如果 系统 正在生成代码,有一个特殊的服务和队列代码生成请求。
如果您选择使用锁,您可以锁定整个资源 Foo 或仅锁定 Code 代。
选项 1:
您将不得不处理 SQLException。今天在大多数应用程序中都使用这个,因为它不会因为有人锁定资源而导致应用程序长时间停顿,从而确保流畅的 用户体验。
您可以使用抽象,例如存储库。定义您自己的应用程序级异常 UniqueCodeViolationException,该异常将由存储库抛出。存储库将尝试{}捕获{} SQLException、处理它并在比较错误代码时将其包装在 UniqueCodeViolationException 中。这不会为您节省检查时间,但至少会隐藏具体错误,并且您只会在一个地方进行处理。
选项 2:
有时候确实需要保证没有并发,所以就用这个选项。在这种情况下,您将不得不为一个用户锁定创建 Foo 的过程,并且不允许其他人甚至能够打开 dialog/form/page如果有锁,则创建 Foo。
这确保了一致性,并通过创建一个基本上无法用于多个目标相同 Foo 的用户的系统来避免问题。您正在构建的应用程序很可能只有一个人负责创建 Foo 或者并发性很低,因此这可能是一个很好的解决方案。
我有朋友在保险的申请中使用这把锁。通常在他们的申请中,一个人会去一个办公室办理一份保险。所以同时为同一个人创建一份保险的可能性很低,但是为同一个人创建多份保险的成本是非常高的。
选项 3:
另一方面,如果您的代码是由 System 生成的,您可以使用 CodeGenerationService 来处理代码生成并确保生成唯一代码。您可以对这些请求进行排队。在服务中的每个生成操作中,您可以检查此代码是否存在以及 return 错误(或抛出异常)。
现在提问4。如果您不希望经常发生冲突,只需在您的数据库中添加一个 Unique Constraint 并将其视为一般意外错误。添加检查 Code 是否已经存在,如果存在则显示错误。
您仍然可以在这里进行并发,因此会有一个微小的变化,即一个用户将添加一个 Foo,而另一个用户将得到一个错误 "Oooops... something whent wrong.. please try again"。因为这将在 100 年内发生一次,所以没关系。
最后一个解决方案将忽略在极少数情况下可能发生的特殊情况,从而使您的系统更加简单。