根据 C# 中的条件保护关键部分

发布于 2024-09-03 01:33:31 字数 1208 浏览 2 评论 0原文

我正在处理一个奇怪的场景。

我正在使用 EntityFramework 在多线程环境中将数据保存(插入/更新)到 SQL 数据库中。问题是我需要访问数据库以查看是否已经创建了具有特定键的寄存器,以便设置字段值(正在执行),或者是新设置不同的值(待定)。这些寄存器由唯一的引导标识。

我已经通过设置锁解决了这个问题,因为我知道实体不会出现在任何其他进程中,换句话说,我在不同的进程中不会有相同的 guid,并且它似乎工作正常。它看起来像这样:

static readonly object LockableObject = new object();
static void SaveElement(Entity e)
{
       lock(LockableObject)
       {
           Entity e2 = Repository.FindByKey(e);
           if (e2 != null)
           {
               Repository.Insert(e2);
           }
           else
           {
               Repository.Update(e2);
           }
       }
}

但这意味着当我有大量的请求需要保存时,它们将排队。

我想知道是否有类似的东西(请仅将其视为一个想法):

static void SaveElement(Entity e)
{
       (using ThisWouldBeAClassToProtectBasedOnACondition protector = new ThisWouldBeAClassToProtectBasedOnACondition(e => e.UniqueId)
       {
           Entity e2 = Repository.FindByKey(e);
           if (e2 != null)
           {
               Repository.Insert(e2);
           }
           else
           {
               Repository.Update(e2);
           }
       }
}

该想法将具有一种基于条件的保护,因此每个实体 e 都会有自己的基于 e.UniqueId 属性的锁。

有什么想法吗?

I'm dealing with a courious scenario.

I'm using EntityFramework to save (insert/update) into a SQL database in a multithreaded environment. The problem is i need to access database to see whether a register with a particular key has been already created in order to set a field value (executing) or it's new to set a different value (pending). Those registers are identified by a unique guid.

I've solved this problem by setting a lock since i do know entity will not be present in any other process, in other words, i will not have same guid in different processes and it seems to be working fine. It looks something like that:

static readonly object LockableObject = new object();
static void SaveElement(Entity e)
{
       lock(LockableObject)
       {
           Entity e2 = Repository.FindByKey(e);
           if (e2 != null)
           {
               Repository.Insert(e2);
           }
           else
           {
               Repository.Update(e2);
           }
       }
}

But this implies when i have a huge ammount of requests to be saved, they will be queued.

I wonder if there is something like that (please, take it just as an idea):

static void SaveElement(Entity e)
{
       (using ThisWouldBeAClassToProtectBasedOnACondition protector = new ThisWouldBeAClassToProtectBasedOnACondition(e => e.UniqueId)
       {
           Entity e2 = Repository.FindByKey(e);
           if (e2 != null)
           {
               Repository.Insert(e2);
           }
           else
           {
               Repository.Update(e2);
           }
       }
}

The idea would be having a kind of protection that protected based on a condition so each entity e would have its own lock based on e.UniqueId property.

Any idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

西瑶 2024-09-10 01:33:31

不要在需要数据库事务或约束的地方使用应用程序锁。

使用锁来防止数据库中出现重复条目​​并不是一个好主意。它限制了应用程序的可扩展性,强制只存在一个可以添加或更新此类记录的实例。或者更糟糕的是,有人最终会尝试将应用程序扩展到多个进程或服务器,这将导致数据损坏(因为锁是单个进程的本地锁)。

您应该考虑的是在数据库和事务中使用唯一约束的组合,以确保添加相同条目的两次尝试都不会成功。一个会成功,另一个将被迫回滚。

Don't use application-locks where database transactions or constraints are needed.

The use of a lock to prevent duplicate entries in a database is not a good idea. It limits the scalability of your application be forcing only a single instance to ever exist that can add or update such records. Or worse, someone will eventually try to scale the application to multiple processes or servers and it will cause data corruption (since locks are local to a single process).

What you should consider instead is using a combination of unique constraints in the database and transactions to ensure that no two attempts to add the same entry can both succeed. One will succeed - the other will be forced to rollback.

紫竹語嫣☆ 2024-09-10 01:33:31

这可能对你有用,你可以锁定 e 的实例:

   lock(e)
   {
       Entity e2 = Repository.FindByKey(e);
       if (e2 != null)
       {
           Repository.Insert(e2);
       }
       else
       {
           Repository.Update(e2);
       }
   }

This might work for you, you can just lock on the instance of e:

   lock(e)
   {
       Entity e2 = Repository.FindByKey(e);
       if (e2 != null)
       {
           Repository.Insert(e2);
       }
       else
       {
           Repository.Update(e2);
       }
   }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文