相关疑难解决方法(0)

在没有竞争条件的情况下使用Entity Framework实现if-not-exists-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存储过程,我可以使用具有锁定提示的事务来确保永远不会发生竞争条件.是否有一种干净的方法来避免实体框架中的竞争条件,而不诉诸存储过程或盲目吞咽异常?

linq-to-entities entity-framework insert

15
推荐指数
1
解决办法
6840
查看次数

通过.net中的SqlTransaction禁用对表的读/写?

如何在.net 2.0中使用SqlTransaction,以便当我开始从表中读取数据时,该表被阻止其他人(其他程序)读取/写入该表?

如果SqlTransaction不是一个好的选择,那是什么?

.net c# vb.net sql-server ado.net

4
推荐指数
1
解决办法
2729
查看次数

解决与“insert-if-not-exists”模式相关的数据库并发问题

我将 Entity Framework Core 3.1.8 与 SQL Server 2016 结合使用。

考虑以下示例(为了清晰起见,进行了简化):

数据库表定义如下:

CREATE TABLE [dbo].[Product]
(
    [Id] INT IDENTITY(1,1) NOT NULL , 
    [ProductName] NVARCHAR(500) NOT NULL,
    CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED (Id ASC) WITH (FILLFACTOR=80),
    CONSTRAINT [UQ_ProductName] UNIQUE NONCLUSTERED (ProductName ASC) WITH (FILLFACTOR=80) 
)
Run Code Online (Sandbox Code Playgroud)

以及以下 C# 程序:

using System;
using System.Linq;
using System.Reflection;

namespace CcTest
{
    class Program
    {
        static int Main(string[] args)
        {
            Product product =  null;

            string newProductName = "Basketball";

            using (CcTestContext context = new CcTestContext())
            using (var …
Run Code Online (Sandbox Code Playgroud)

c# sql-server concurrency entity-framework entity-framework-core

4
推荐指数
1
解决办法
4663
查看次数