C# 基于C中的条件保护临界截面#
我正在处理一个非常糟糕的情况 我使用EntityFramework在多线程环境中保存(插入/更新)到SQL数据库中。问题是,我需要访问数据库,以查看是否已经创建了一个具有特定键的寄存器,以便设置字段值(正在执行),或者设置不同的值(挂起)是新的。这些寄存器由唯一的guid标识 我通过设置一个锁解决了这个问题,因为我知道实体不会出现在任何其他进程中,换句话说,我在不同的进程中不会有相同的guid,而且它似乎工作正常。看起来是这样的:C# 基于C中的条件保护临界截面#,c#,multithreading,conditional,critical-section,C#,Multithreading,Conditional,Critical Section,我正在处理一个非常糟糕的情况 我使用EntityFramework在多线程环境中保存(插入/更新)到SQL数据库中。问题是,我需要访问数据库,以查看是否已经创建了一个具有特定键的寄存器,以便设置字段值(正在执行),或者设置不同的值(挂起)是新的。这些寄存器由唯一的guid标识 我通过设置一个锁解决了这个问题,因为我知道实体不会出现在任何其他进程中,换句话说,我在不同的进程中不会有相同的guid,而且它似乎工作正常。看起来是这样的: static readonly object LockableO
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);
}
}
}
但这意味着当我有大量的请求要保存时,它们将排队
我想知道是否有这样的事情(请把它当作一个想法):
这个想法是有一种基于条件的保护,这样每个实体e都有自己的基于e.UniqueId属性的锁
有什么想法吗?这可能适合您,您可以锁定e的实例:
lock(e)
{
Entity e2 = Repository.FindByKey(e);
if (e2 != null)
{
Repository.Insert(e2);
}
else
{
Repository.Update(e2);
}
}
在需要数据库事务或约束的地方不要使用应用程序锁。 使用锁来防止数据库中的重复条目不是一个好主意。它限制了应用程序的可伸缩性,因为它只能强制存在一个可以添加或更新此类记录的实例。更糟糕的是,最终会有人试图将应用程序扩展到多个进程或服务器,这将导致数据损坏(因为锁是单个进程的本地锁)
<强>您应该考虑的是在数据库和事务中使用独特的约束< /强>,以确保两个尝试添加相同的条目都可以成功。一个会成功,另一个会被强制回滚。
为什么不使用DB事务或存储过程?这在访问数据库时一点也不坏,但是。。。如果您访问的是任何其他共享资源,即假设存储库访问的是xml文件或循环文件。或者更好,让我们假设您不是通过访问数据库来工作,而是访问内存中的静态字典……我们是在讨论EntityFramework的并发管理,还是一般的并发?EF是专门为与数据库接口而设计的,因此您将使用EF管理并发数据操作的策略和技术应该与您处理数据库的事实保持一致。如果您需要提供对其他资源(如文件)的并发、可写访问—您不再处理EF—并且您将采用的技术特定于该特定域。并发编程没有单一的灵丹妙药。我说的是一般的并发。为了说明,我用EF作为一个例子,这是一个很好的观点,但是我们应该考虑实体E是不稳定的,这可能不起作用,因为它每次都会锁定不同的E实例。 lock(e)
{
Entity e2 = Repository.FindByKey(e);
if (e2 != null)
{
Repository.Insert(e2);
}
else
{
Repository.Update(e2);
}
}