EF4 / WCF SaveChanges () Лучшая практика - PullRequest
1 голос
/ 24 июня 2011

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

Есть ли лучший способ?

[OperationContract]
public User SaveUser(User entity)
{
    bool _IsDeleted = false;
    using (DatabaseEntities _Context = new DatabaseEntities())
    {
        switch (entity.ChangeTracker.State)
        {
            case ObjectState.Deleted:
                //delete
                _IsDeleted = true;
                _Context.Users.Attach(entity);
                _Context.DeleteObject(entity);
                break;
            default:
                //everything else
                _Context.Users.ApplyChanges(entity);
                break;
        }
        // now, to the database
        try
        {
            // try to save changes, which may cause a conflict.
            _Context.SaveChanges(System.Data.Objects.SaveOptions.None);
        }
        catch (System.Data.OptimisticConcurrencyException)
        {
            // resolve the concurrency conflict by refreshing 
            _Context.Refresh(System.Data.Objects.RefreshMode.ClientWins, entity);
            // Save changes.
            _Context.SaveChanges();
        }
    }
    // return
    if (_IsDeleted)
        return null;
    entity.AcceptChanges();
    return entity;
}

Ответы [ 2 ]

6 голосов
/ 24 июня 2011

Почему вы делаете это с самообследованием сущностей?Что не так с этим:

[OperationContract]
public User SaveUser(User entity)
{
    bool isDeleted = false;
    using (DatabaseEntities context = new DatabaseEntities())
    {
        isDeleted = entity.ChangeTracker.State == ObjectState.Deleted;
        context.Users.ApplyChanges(entity); // It deletes entities marked for deletion as well

        try
        {
            // no need to postpone accepting changes, they will not be accepted if exception happens
            context.SaveChanges(); 
        }
        catch (System.Data.OptimisticConcurrencyException)
        {
            context.Refresh(System.Data.Objects.RefreshMode.ClientWins, entity);
            context.SaveChanges();
        }
    }

    return isDeleted ? null : entity;
}
2 голосов
/ 24 июня 2011

Если я не ошибаюсь, люди обычно не выставляют свои объекты Entity Framework непосредственно в сервисе WCF.Entity Framework обычно рассматривается как уровень доступа к данным, а WCF - это скорее интерфейсный уровень, поэтому они размещаются на разных уровнях.

Объект передачи данных (DTO) используется в методах WCF.Как правило, это POCO, который вообще не отслеживает состояние.Затем DTO сопоставляется с сущностью либо вручную, либо с помощью структуры, такой как AutoMapper.

Обычно клиенты должны знать, «добавляют» ли они или «обновляют» объект, и я лично предпочел бы, чтобы их было дваотдельные операции на интерфейсе сервиса.Кроме того, я бы определенно потребовал бы, чтобы они использовали отдельный метод для удаления объекта.Однако, если вам абсолютно необходимо общее «Сохранить», вы должны быть в состоянии определить, является ли данный вам объект «новым» или нет, основываясь на наличии (или отсутствии) значения первичного ключа.

Большая часть кода может быть помещена в общую утилиту.Например, предположим, что ваш шаблон T4 создает атрибуты для значений ключей ваших сущностей, вы можете автоматически определить, присутствуют ли значения ключей, и соответственно выполнить вставку / обновление.Кроме того, блок try SaveChanges catch retry, который вы используете - хотя, возможно, и не нужен - может быть легко помещен в простой служебный метод, чтобы быть более СУХИМЫМ.

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