0

これが私の現在のコードです

[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 メソッドであるためです。多くの人が同時に投稿でき、複数のアイテムが同じ日付で作成される可能性があります。

ロックをかけても解決しませんでした。複数のアイテムがまだ同じ日付で作成されています。私はロックを正しい方法で入れていますか?

4

1 に答える 1

3

私はロックを正しい方法で入れていますか?

いいえ、あなたのコードを見てみましょう:

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

これは毎回新しいロックを作成しているため、別のリクエストがすでにロックを所有していることはありません。

ロックはすべてのリクエスト間で共有する必要があります。つまり、フィールドである必要があります...静的フィールド(ick)またはすべてのリクエスト間ですでに共有されているオブジェクト内のインスタンスフィールドのいずれかです。ただし、これはまだ1 つのボックスの 1 つの AppDomain 内でしか機能しません。うまくスケーリングできないか、AppDomain のリサイクルに直面しても機能しません。

代わりにデータベース制約を使用してこれを処理する必要があるように思われます-レコードが既に存在するかどうかを確認し、存在しない場合は挿入しててください-別のリクエストが間にあると失敗することを理解してください。

于 2013-01-24T06:52:05.507 に答える