1

我正在构建一个 ASP Web API 项目,使用 SQL Server 进行存储,并使用实体框架连接到它。

存储中的几个表包含唯一约束以强制它们中的值的唯一性。在向这些表添加值之前,我的应用程序会检查以确保这些值不存在。

构建应用程序时,每个请求都存在一个 DbContext。但是,我想到两个请求可能会尝试将相同的值插入表中。请求 A 将检查表中是否存在该值,请求 B 也是如此。两者都确定该值需要添加,并将其添加到 DbSet。当调用 SaveChanges 时,一个请求会成功,一个请求会因为唯一约束失败而失败。

Entity Framework 如何解决这些问题?我计划创建存储过程来检索或创建值,我认为应该解决它(保证原子性的存储过程),但我会更热衷于仅使用实体框架本身解决这个问题的方法。我想我喜欢排队加载仅在调用 DbContext.SaveChanges() 时执行的操作的想法,但显然存储过程解决方案意味着数据库交互将在 SaveChanges() 之前发生。

4

1 回答 1

2

此问题并非特定于实体框架(尽管 EF 当然也有围绕 UNIQUE 约束的其他限制)。这在任何类似的服务器-客户端模型中都很常见。由于唯一性将在请求时由数据库服务器强制执行,因此在您尝试插入之前,没有万无一失的方法可以提前知道是否会违反约束。

也就是说,提前检查唯一性应该是一个非常便宜的操作(在 SQL Server 上,UNIQUE 约束也会为您提供该列的索引),因此取决于您希望应用程序尝试重复插入的频率,这应该涵盖您的大部分案件。但是,如果一开始就很少有重复插入尝试,您可以避免每次插入都进行额外的往返,并在发生异常时处理它。

处理异常不需要很复杂,特别是如果最终用户有办法修改数据并尝试重试。如您所说,如果您在单个事务中排队多个插入,您可能需要检查特定约束名称的异常(或内部异常),以便您知道哪个实体对象是重复的。(同样,EF 并不真正支持直接处理 UNIQUE 约束异常,所以这可能是现在让您最痛苦的部分。)

注意:我不建议将插入作为存储过程重新工作,以规避同时尝试重复条目的罕见机会。你最好确保你的应用程序尽可能优雅地处理这个(以及其他可能有很多的 SQL 异常)。但是,如果您发现在您的情况下确实没有其他方法,那么 sproc 可能是目前最简单的方法。请记住,为了解决非常罕见的边缘情况,它可能会放弃更易于维护的代码。

于 2013-06-21T00:12:59.080 回答