Weird! После переноса в ef core 3 вызов async Context.Set <T>(). Add (t) создает 9 одинаковых записей вместо одной - PullRequest
0 голосов
/ 21 октября 2019

Я только что перешел на mvc net core 3.0 с net core 2.2. Теперь каждый раз, когда я пытаюсь добавить новую запись в базу данных, приложение создает 9 копий той же записи в базе данных. У меня есть много таблиц в моей базе данных, и это происходит на каждой из них. Когда я использовал net core 2.2, все работало нормально.

Я использую этот код для добавления новой записи в БД:

Файл контекста БД:

public virtual async Task<T> AddAsync(T t)
{
    Context.Set<T>().Add(t);
    await Context.SaveChangesAsync();
    return t;
}

Эта функция вызывается из файла репозитория db companies:

public async Task<Company> AddCompany(Company item)
{
    var savedItem = await base.AddAsync(item);

    var exist = Context.Companies.Find(savedItem.Id);
    if (exist == null) return exist;

    return savedItem;
}

Репозиторий Db вызывается из файла репозитория компании:

public async Task<Company> AddCompany(Company item)
{
    return await _companiesDbRepository.AddCompany(item);
}

Репозиторий компаний вызывается из контроллера Mvc:

public async Task<IActionResult> AddCompany(Company item)
{
    var newcompany = await _companiesRepository.AddCompany(item);
}

Контроллер вызывается из jquery ajax onКлиентская сторона и запрос к контроллеру отправляют по кнопке «Добавить компанию» клик.

$(document).on("click", "#addCompany",
    function (e) {
        e.preventDefault();
        e.stopPropagation();
        var route="...";
        var formId="...";
     var form = $(formId);
        form.validate();
        if (!form.valid()) return;
        addCompany(route,formId);
});

function addCompany(route, formId) {

alert("start");

    var form = $(formId);
        var formData = form.serialize();

        $.ajax({
            async: true,
            url: route,
            type: "POST",
            cache: false,
            data: formData,

            success: function (result) {
                alert("sucess");


            },
            error: function (xhr) {
                alert("error");

            }
        });
};

Я вижу на экране «старт» оповещение 9 раз. Через некоторое время я вижу предупреждение об успехе 9 раз.

Когда я пытаюсь отследить код в отладчике, я вижу, что выполнение хаотично переходит от одной функции к другой - несколько раз одна строка кода водна функция, после этого несколько раз в другую функцию. После этого он возвращается к другой строке первой функции, и все повторяется 20-30 раз.

Пожалуйста, помогите. Я никогда не видел ничего странного за всю свою долгую карьеру программиста.

И самое странное, что все эти 9 записей обычно сохраняются на сервере MS Db. У них есть все поля и ключи. Но когда я открываю любой из них на экране, это показывает, что все поля пусты. Но с помощью того же приложения я все еще могу нормально открывать и видеть на экране записи, которые были сохранены до того, как я перешел на Core 3.0

Ответы [ 2 ]

0 голосов
/ 23 октября 2019

решаемая.

Я обнаружил, что каждая кнопка «Добавить компанию» запускает клики, отправляя несколько запросов AJAX. Использование $ (this) .off ('click') и т.п. не работает вообще.

Решение:

$(document).on("click", "#addCompany",
    function (e) {
        e.preventDefault();
        **e.stopPropagation();**
      ......
});

replaced by

$(document).on("click", "#addCompany",
    function (e) {
        e.preventDefault();
        **e.stopImmediatePropagation();**

});

Теперь все работает идеально. «stopImmediatePropagation ()» подавил все повторяющиеся триггеры «щелчка» события.

0 голосов
/ 22 октября 2019

Я не вижу никакой причины в приведенном вами коде, почему он будет сохранять запись более одного раза.

Я вижу, что выполнение хаотично переходит от одной функции к другой

Это нормально, если запущено несколько потоков. Во время отладки на панели инструментов Visual Studio есть раскрывающийся список «Поток». Когда вы видите, что он «перепрыгивает» на другую часть кода, обратите внимание, что номер потока, выбранный в этом раскрывающемся списке, отличается.

Но это может указывать на то, что обрабатывается несколько запросов (т.е. вы на самом делеотправка 9 запросов). Вы должны быть в состоянии проверить это на стороне клиента (кем бы он ни был), или вы можете удалить все свои точки останова и установить только одну в действии вашего контроллера:

public async Task<IActionResult> AddCompany(Company item)
{
    //set breakpoint here
    var newcompany = await _companiesRepository.AddCompany(item);
}

Когда эта точка останова достигнута, нажмитеF5. И просто посчитайте, сколько раз была достигнута эта точка останова.

В качестве примечания, я не совсем понимаю, что вы здесь делаете:

public async Task<Company> AddCompany(Company item)
{
    var savedItem = await base.AddAsync(item);

    var exist = Context.Companies.Find(savedItem.Id);
    if (exist == null) return exist;

    return savedItem;
}

Если элемент был сохранен правильнотогда savedItem.Id будет иметь значение (при условии, что это первичный ключ, сгенерированный базой данных?). Так зачем вам искать его, чтобы увидеть, есть ли он там? В конце концов, если он не сохранится успешно, возникнет исключение.

Тогда зачем вы возвращаете exist, если это null? Имейте в виду, что это никогда не произойдет по той же причине (если бы не сохранить, было бы выброшено исключение, и вы бы никогда не добрались до этой строки кода).

Я чувствую, что вы могли бы упростить этона это:

public Task<Company> AddCompany(Company item)
{
    return base.AddAsync(item);
}

И это вызывает еще одно упрощение (и незначительное повышение производительности), которое вы можете сделать: если вы собираетесь вернуть результат только await в вашем методе, вы можете отказатьсяс async и await в этом методе и просто верните Task.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...