使用 C# 的实体框架中的脏读概念

问题描述 投票:0回答:1

我正在使用实体框架和 C# 开发 Web API。我需要脏读的解决方案。

我已经尝试过以下方法和事务方法,我需要脏读的解决方案。

脏读或幻读是用户没有更新最新数据的现象。

假设用户A打开了推销员网页

用户B也打开了同一个推销员网页

A已加载业务员ID 1001,B也已加载1001 将推销员姓名更改为 X 并保存。

但是 B 看到的是旧数据,如果 B 将销售员姓名更改为 Y,A 的更改将被覆盖。所以我们应该阻止 B 将更改写入 DB。

所以我需要基于上述概念的解决方案。

using (var transaction = db.Database.BeginTransaction())
{
    try
    {
        db.SaveChanges();
        transaction.Commit();
    }
    catch (Exception excp)
    {
        throw excp;
    }
}

return Ok();

下面是我尝试过的代码

using (var transaction = db.Database.BeginTransaction())
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    KSTU_COUNTER_MASTER kcm = new KSTU_COUNTER_MASTER();
    kcm.obj_id = Common.GetNewGUID();
    kcm.company_code = Common.CompanyCode;
    kcm.branch_code = Common.BranchCode;
    kcm.counter_code = c.CounterCode;
    kcm.counter_name = c.CounterName;
    kcm.Maincounter_code = c.MaincounterCode;
    kcm.obj_status = c.ObjectStatus;
    kcm.UpdateOn = Framework.Common.GetDateTime();
    kcm.UniqRowID = Guid.NewGuid();

    db.KSTU_COUNTER_MASTER.Add(kcm);

    try
    {
        db.SaveChanges();
        transaction.Commit();
    }
    catch (Exception excp)
    {
        throw excp;
    }
}

return Ok();
c# entity-framework asp.net-web-api concurrency dirtyread
1个回答
0
投票

假设用户A打开了推销员网页 用户B也打开了相同的推销员网页 A 已加载销售员 ID 1001,B 也加载了 1001 A 将销售员姓名更改为 X 并保存。

评论是正确的,这是一个需要客户端乐观并发检查的问题,而不是数据库事务。但我想解释一下为什么会这样。

您实际上可以在此处以快照、可重复读取或可串行隔离级别使用事务。 A 和 B 都能够打开相同的销售人员页面并执行编辑,但无论哪一个尝试保存 last 都会导致错误(根据隔离级别,此错误可能是死锁)。但重写异常会被阻止。

但是,要实现这一点,您必须保持数据库连接,并且从每个用户导航到“推销员网页”到用户保存数据期间事务保持打开状态。在 Web 应用程序中,您无法了解或控制该时间有多长。在客户端-服务器应用程序中,您可以某种程度上实现此目的,但在网络应用程序中,这种方法几乎被普遍放弃,转而支持客户端乐观并发。

© www.soinside.com 2019 - 2024. All rights reserved.