ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CodeGo.net>当行可能不存在时,如何原子递增?

2019-11-20 09:08:50  阅读:168  来源: 互联网

标签:entity-framework-6 c net entity-framework


假设我有一个DbSet< Item>派生自DbContext的MyContext.项,其中项定义如下.

public class Item
{
    [Key]
    public string Key { get; set; }

    [ConcurrencyCheck]
    public int Value { get; set; }
}

给定一个键,我想以原子方式递增相应的值,其中表中尚未存在的键的隐式值为0.也就是说,以原子方式递增表中不存在的键的结果为1.我目前的做法:

public static async Task IncrementAsync(string key)
{
    using (var context = new MyContext())
    {
        while (true)
        {
            var item = await context.Items.FindAsync(key);
            if (item == null)
            {
                context.Items.Add(new Item { Key = key, Value = 1 });
            }
            else
            {
                item.Value++;
            }
            try
            {
                await context.SaveChangesAsync();
                break;
            }
            catch (DbUpdateException)
            {
                continue;
            }
        }
    }
}

当对IncrementAsync的许多调用同时运行时,此操作将因实时锁定而失败.

>正确的方法是什么?
> while循环是否应该在使用范围之外,以便每次尝试都获得一个新的上下文?我尝试了一下,它使一切正常,但是我觉得创建和破坏这么多上下文的效率很低.
>我是否缺少有关上下文跟踪更改方式的信息?

我的实体框架经验基本上只用于查询,因此,如果您能解释这段代码中我做错的更好的细节,我将非常感谢.

编辑
因为选择的答案没有明确,所以将正确的代码放在这里.请注意,在DbUpdateException之后如何从不重用上下文.

public static async Task IncrementAsync(string key)
{
    while (true)
    {
        using (var context = new MyContext())
        {
            var item = await context.Items.FindAsync(key);
            if (item == null)
            {
                context.Items.Add(new Item { Key = key, Value = 1 });
            }
            else
            {
                item.Value++;
            }
            try
            {
                await context.SaveChangesAsync();
                break;
            }
            catch (DbUpdateException)
            {
                continue;
            }
        }
    }
}

解决方法:

您需要不尝试之间共享上下文.如果根本不对具有DbUpdateException的上下文执行任何操作,就好像您没有明确清理该上下文一样,它可能永远不会返回正常状态.

我希望外部环境会引起问题.如果根据时间发生对单个键的并发调用,则可能会创建错误的上下文设置(由于错误处理程序,该上下文设置会不断被忽略.

除非我误会了数据库中存在密钥的事实,否则不会删除“要添加”的版本.您最终将遇到以下情况之一:

Add "1", 2

要么

Add "1", 1
Update "1", 2

取决于您的第二次迭代是捕获第一次迭代的对象还是新的对象.

这些都不成功,因此您会遇到连续错误.

标签:entity-framework-6,c,net,entity-framework
来源: https://codeday.me/bug/20191120/2042929.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有