Sha*_*ser 15 linq-to-entities entity-framework insert
使用LINQ-to-Entities 4.0,是否有正确的模式或结构来安全地实现"if not exists then insert"?
例如,我目前有一个跟踪"用户收藏夹"的表 - 用户可以在收藏夹列表中添加或删除文章.
基础表不是真正的多对多关系,而是跟踪一些其他信息,例如添加收藏夹的日期.
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);
Run Code Online (Sandbox Code Playgroud)
根据需要,使用相同的用户/文章对插入两个收藏夹会导致重复键错误.
我目前使用C#在数据层中实现了"if not exists then insert"逻辑:
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();
}
Run Code Online (Sandbox Code Playgroud)
这种实现的问题在于它易受竞争条件的影响.例如,如果用户双击"添加到收藏夹"链接,则可以将两个请求发送到服务器.第一个请求成功,而第二个请求(用户看到的请求)失败,UpdateException包含重复键错误的SqlException.
使用T-SQL存储过程,我可以使用具有锁定提示的事务来确保永远不会发生竞争条件.是否有一种干净的方法来避免实体框架中的竞争条件,而不诉诸存储过程或盲目吞咽异常?
Hen*_*ken -3
您可以尝试将其包装在与“著名”try/catch 模式相结合的事务中:
using (var scope = new TransactionScope())
try
{
//...do your thing...
scope.Complete();
}
catch (UpdateException ex)
{
// here the second request ends up...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6840 次 |
| 最近记录: |