LOCK每个日期只允许一条记录

时间:2013-01-24 06:46:33

标签: c# asp.net .net multithreading locking

这是我当前的代码

[HttpPost]
    public void AddMenuItem(DateTime MenuDate, string MenuItemIds_String)
    {
        if (string.IsNullOrEmpty(MenuItemIds_String)) { return; }
        var MenuItemIds = MenuItemIds_String.Split(',').Select(x=>int.Parse(x));

        int JamaatId = 1;

        object thisLcok = new object();
        lock (thisLcok)
        {
            bool ParentPresent = db.DailyMenus.SingleOrDefault(x => x.JamaatId == JamaatId && x.MenuDate == MenuDate) != null;
            if (!ParentPresent)
            {
                db.DailyMenus.Add(new DailyMenu { JamaatId = JamaatId, MenuDate = MenuDate, MenuNoteText = string.Empty });
                db.SaveChanges();
            }
        }
        DailyMenu parentMenu = db.DailyMenus.Single(x => x.JamaatId == JamaatId && x.MenuDate == MenuDate);

        foreach(int id in MenuItemIds){
            bool AlreadyExits = parentMenu.DailyMenuItems.SingleOrDefault(x => x.MenuItem == db.MenuItems.Find(id)) != null;
            if (!AlreadyExits)
            {
                db.DailyMenuItems.Add(new DailyMenuItem { MenuItem = db.MenuItems.Find(id), DailyMenu = parentMenu });
                db.SaveChanges();
            }
        }
    }

我只想创建父记录如果不存在。由于这是一个http post方法。许多人可以同时发布它,并且可以在同一日期创建多个项目。

放锁并没有解决它。仍在为同一日期创建多个项目。我正确地锁定了吗?

1 个答案:

答案 0 :(得分:3)

  

我是否正确地锁定了?

没有。我们来看看你的代码:

object thisLcok = new object();
lock (thisLcok)
{
    ...
}

每次创建一个 new 锁定 - 因此另一个请求已经拥有锁定是不可能的。

您的锁需要在所有请求之间共享。这意味着它需要是一个字段...静态字段(ick)或某个对象中的实例字段,它已在所有请求之间共享。但是,这个仍然只能在单个AppDomain中,在一个盒子上运行 - 它不能很好地扩展,或者面对AppDomain回收工作。

在我看来,你可能应该使用数据库约束来处理这个 - 所以检查记录是否已经存在,如果没有,尝试插入它 - 了解你如果另一个请求介于两者之间,则会失败。