Entity Framework Core 仓储模式 - 重复检查

3

我正在尝试找出一种解决方案,以检查是否有添加行的字段会破坏不应重复的任何字段。我使用存储库模式,因此我想在存储库中创建一个方法来执行此操作。

在这个示例中,我正在尝试添加一个公司,在控制器中添加之前,它调用CompanyRespository中的此方法:

    public bool Exists(Company company, bool ignoreId)
    {
        if (!ignoreId)
        {
            if (context.Companies.Any(c => c.Id == company.Id)) return true;
        }
        if (context.Companies.Any(c => c.TextId == company.TextId)) return true;
        if (context.Companies.Any(c => c.Email == company.Email)) return true;
        if (context.Companies.Any(c => c.PhoneNumber == company.PhoneNumber)) return true;
        return false;
    }

我遇到的问题是如何返回错误信息,以便控制器可以将错误发送到客户端。显而易见的解决方案是发送异常而不是返回true。然而,如果我只是想调用此方法来判断是否存在这些参数的公司,则不希望发送异常,我只需要在两种情况下返回布尔值。
简化的问题是:在这种情况下,创建另一个方法CheckDuplication()并返回异常而不是布尔值是否属于不良做法?如果是,那么在使用Entity Framework Core保存到数据库之前检查重复字段的正确方法是什么?

3
使用一个更复杂的返回对象来保存所需信息,类似于使用ModelState的方式。 - Nkosi
2
我倾向于赞同@Nkosi的观点。为什么不只是返回一个模型,其中包含两个属性,一个是IEnumerable<Exception>或IList<Exception>(根据您的需要),另一个是指示存在的布尔值?[已编辑以提高清晰度。] - Trioj
2
我认为将存在性检查和验证检查分开并没有本质上的问题。拥有一个仅返回布尔值的Exists()方法和一种抛出异常或返回某种可枚举对象的Validate()方法是可以的。如果将这两个东西合并成一个模型没有意义,那就不要合并。坚持你最初的计划。缺点是每次向表中添加新字段时都需要维护两个方法。将所有内容合并到一个方法中以返回一个对象可能会使它变得更加笨重。 - Trioj
嗯...如果你正在使用SQL数据库,为什么不在DB上设置唯一索引或某些检查约束呢?这样当你尝试保存时,EF就会为你进行检查。注意,如果你使用的是MongoDB,则不需要这样做。 - federico scamuzzi
我认为这两种方法将是验证方法的最佳选择,其中validate方法返回异常列表,以便在控制器中解析到ModelState。我已经使用了唯一约束,但我在互联网上找到的唯一方法涉及捕获异常,然后进行大量转换到不同对象和笨拙的代码,我想要一个更清晰的解决方案。 - Richard
1个回答

1
拥有一个独立的验证检查是很好的,可以让您编写更加用户友好的应用程序。然而,不要犯依赖此检查来确保数据完整性的错误。多线程将是最令人担忧的原因。Sql DB可以更好地保护数据完整性,因此建议在每个字段上定义唯一约束(例如,查看使用流畅API设置唯一约束?)。当然,这将引发EF异常,但可以捕获并检查以确定它们是否违反了约束。那样,如果需要,仍可以返回布尔值。
另外,通过使用OR(||),可以更有效地编写Exits方法,这样就不必触发太多的SQL查询。

我已经启用了约束条件,因为我不想让数据库处于糟糕的状态,如果数据库有一种防止糟糕状态的方法,那么我将主要使用该方法。然而,我希望有一个用户友好的解决方案,我觉得验证方法是这样的,只需返回一个易于解析的异常,而不是检查 ef 异常。谢谢你的附注!尝试过类似的东西,但没有意识到“||”是这样做的方式。 - Richard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接