Должен ли я проверить, существует ли строка перед удалением? - PullRequest
1 голос
/ 16 декабря 2010

Я использую Mssql в качестве базы данных и EF4 в качестве ORM / DAL.
Мой вопрос касается следующего кода:

public static void DeleteBuilding(int buildingId, int countryId)
{
    PlayerBuilding playerBuilding = new PlayerBuilding()
    {
        CountryID = countryId,
        BuildingID = buildingId
    };
    Entities.PlayerBuildings.Attach(playerBuilding);
    Entities.PlayerBuildings.DeleteObject(playerBuilding);
    Entities.SaveChanges();
}

Если строка существует, это работает очень хорошо, если нет Я получаю исключение ( Оператор хранения, вставки или удаления затронул неожиданное количество строк (0). Возможно, объекты были изменены или удалены с момента загрузки объектов. Обновить записи ObjectStateManager. )
Должен ли я совершить поездку в оба конца в базу данных, чтобы проверить, существует ли строка следующим образом:

public static void DeleteBuilding(int buildingId, int countryId)
{
    PlayerBuilding playerBuilding = (from p in Entities.PlayerBuildings
                                     where p.BuildingID == buildingId && p.CountryID == countryId
                                     select p).FirstOrDefault();
    if (playerBuilding != null)
    {
        Entities.PlayerBuildings.DeleteObject(playerBuilding);
        Entities.SaveChanges();
    }
}

Я думаю, что дополнительная поездка туда и обратно не нужна, потому что без EF с простым SQLможет просто удалить строку с помощью одной команды DELETE.

Какая практика лучше?

1 Ответ

0 голосов
/ 16 декабря 2010

Эта ошибка является побочным эффектом оптимистичного параллелизма Entity Framework .

В принципе, кто-то другой мог удалить запись между вами, когда вы ее извлекали. Или, может быть, вы сделали что-то с сущностью до этого кода.

Попробуйте запустить его в изолированной среде (например, в модульном тесте), чтобы убедиться, что проблема все еще возникает.

Да, вы можете проигнорировать и снова получить запись, или вы можете использовать ObjectContext.Refresh :

public static void DeleteBuilding(int buildingId, int countryId)
{
    PlayerBuilding playerBuilding = new PlayerBuilding()
    {
        CountryID = countryId,
        BuildingID = buildingId
    };

    try
    {
       Entities.PlayerBuildings.Attach(playerBuilding);
       Entities.PlayerBuildings.DeleteObject(playerBuilding);
       Entities.SaveChanges();
    }
    catch (OptimisticConcurrencyException)
    {
       Entities.Refresh(RefreshMode.ClientWins, playerBuilding);
       Entities.SaveChanges();
    }
}

На заметку - может быть, это потому, что ваш метод static ? Как вы реализуете свой контекст? Я надеюсь, что вы не используете синглтон. (

Здесь есть превосходная статья о оптимистическом параллелизме EF здесь , в которой более подробно объясняется, почему вы получаете эту ошибку, и какие шаги можно предпринять для ее устранения. 1024 *

...