gpt4 book ai didi

entity-framework - 在没有竞争条件的情况下使用 Entity Framework 实现 if-not-exists-insert

转载 作者:行者123 更新时间:2023-12-03 20:59:59 25 4
gpt4 key购买 nike

使用 LINQ-to-Entities 4.0,是否有正确的模式或构造来安全地实现“如果不存在则插入”?

例如,我目前有一个跟踪“用户收藏夹”的表格 - 用户可以从他们的收藏夹列表中添加或删除文章。

基础表不是真正的多对多关系,而是跟踪一些附加信息,例如添加收藏夹的日期。

CREATE TABLE UserFavorite
(
FavoriteId int not null identity(1,1) primary key,
UserId int not null,
ArticleId int not null
);

CREATE UNIQUE INDEX IX_UserFavorite_1 ON UserFavorite (UserId, ArticleId);

根据需要插入具有相同用户/文章对的两个收藏夹会导致重复键错误。

我目前已经使用 C# 在数据层中实现了“如果不存在则插入”逻辑:
if (!entities.FavoriteArticles.Any(
f => f.UserId == userId &&
f.ArticleId == articleId))
{
FavoriteArticle favorite = new FavoriteArticle();
favorite.UserId = userId;
favorite.ArticleId = articleId;
favorite.DateAdded = DateTime.Now;

Entities.AddToFavoriteArticles(favorite);
Entities.SaveChanges();
}

这种实现的问题在于它容易受到竞争条件的影响。例如,如果用户双击“添加到收藏夹”链接,则可以向服务器发送两个请求。第一个请求成功,而第二个请求(用户看到的请求)失败,出现 UpdateException,为重复键错误包装 SqlException。

通过 T-SQL 存储过程,我可以使用带有锁提示的事务来确保永远不会发生竞争条件。是否有一种干净的方法可以避免 Entity Framework 中的竞争条件,而无需求助于存储过程或盲目吞下异常?

最佳答案

您还可以编写一个使用 sql 2005+ 中的一些新技巧的存储过程

在更新语句中使用您的组合唯一 ID(用户 ID + 文章 ID),然后使用 @@RowCount 函数查看行数是否 > 0,如果为 1(或更多),则更新已找到与您的用户 ID 和文章 ID 匹配的行,如果它是 0,那么你就可以插入了。

例如

更新 tablex set userID = @UserID, ArticleID = @ArticleID(你可以在这里有更多的属性,只要 where 包含一个组合的唯一 ID) where userID = @UserID and ArticleID = @ArticleID

如果(@@RowCount = 0)
开始
插入表格...
结尾

最重要的是,这一切都在一次调用中完成,因此您不必先比较数据,然后再确定是否应该插入。当然,它会停止任何重复的插入并且不会抛出任何错误(优雅地?)

关于entity-framework - 在没有竞争条件的情况下使用 Entity Framework 实现 if-not-exists-insert,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4189954/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com