Уровень обслуживания приложений в виде статических классов

StackOverflow https://stackoverflow.com/questions/2283855

Вопрос

В моем приложении ASP.NET MVC у меня есть проект, который содержит весь уровень бизнес-логики / сервиса.Этот проект взаимодействует с моей базой данных (Entity framework), которая расположена в отдельном проекте.

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

 ServiceLayer.Accounts.CreateAccount(userName, passWord) //etc..

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

    private static AllRepos _Repos;
    private static AllRepos Repos { 
       get 
        { 
           if(_Repos == null)
              _Repos = new AllRepos();

           return _Repos
        }
    }

    public static void CreateAccount(string username, password)
    {
        string salt = GenerateSalt();
        Account newAccount = DatabaseLayer.Models.Account
              { 
              Name = username,
              Password = HashPassword(password, salt),
              Salt = salt
              };
        Repos.AddAccount(newAccount);      
    }

Потому что я не хотел делать следующее повсюду в моем сервисном слое:

 AccountRepository Accounts = new DatabaseLayer.AccountRepository();

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

 public class AllRepos
 {

    private AccountRepository _Accounts;

    public AccountRepository Accounts
    {
        get
        {
            if (_Accounts== null)
                _Accounts= new AccountRepository();

            return _Accounts;
        }
    }

    // the same is done for every other repository (currently have about 10+)
  }

Который использовался в статических классах сервисного уровня.

Поскольку все мои классы уровня обслуживания являются статическими, а Repos поле также статично, очевидная проблема, с которой я продолжаю сталкиваться, заключается в том, что один и тот же объект извлекается из нескольких datacontexts, вызывая странное поведение при обновлениях / удалениях.

Я понимаю, что этого следует ожидать, если я использую статические члены / классы, как я делал, поскольку они продолжаются на протяжении всего жизненного цикла приложения, но есть ли способ иметь возможность использовать уровень сервиса как ServiceLayer.Accounts.Method() без необходимости создавать нестатический класс, который необходимо создавать везде, где он используется, и не сталкиваться с проблемами CRUD из-за нескольких экземпляров datacontext?

Это было полезно?

Решение

Ваш подход к этому действительно не рекомендуется.Лично я бы никогда не допустил такого подхода в своей команде.Недостатки:

  1. Основные проблемы с потоками, с которыми вы сталкиваетесь, которые непросто решить
  2. Вы вообще не можете проверить это очень легко.
  3. Нереалистичная абстракция вашего доступа к данным

Самая большая причина создания экземпляров репозиториев заключается в том, что вы можете внедрять зависимости, если вам нужно.Наиболее известный аргумент в пользу этого - модульное тестирование, чтобы вы могли имитировать зависимости, но я создал несколько репозиториев, у которых есть зависимости интерфейса, которые изменяются в производственном коде.

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

Другие советы

Я не уверен, почему вы так категорически против использования экземпляров.Помимо того факта, что код, который у вас есть сейчас, излишне сложен, использование статических типов также усложняет модульное тестирование.Статический тип подобен синглтону, который вы не можете подделать / заменить.Мне кажется, что ваш реальный вопрос может заключаться в следующем: "Как мне управлять экземплярами моего сервисного уровня в течение всего срока службы?" Обычно вы делаете это, имея по одному экземпляру на веб-запрос.В приложении ASP.NET MVC вы можете создайте новый контейнер DI через ControllerFactory и обработайте все это. [PDF]

Вам нужно обрабатывать область вашего objectcontext преднамеренным образом, например, выполняя Шаблон единицы работы

Кроме того, я действительно думаю, что вам следует пересмотреть делать все статичным, поскольку womp говорит, что вы получаете очень высокую связь и это очень затрудняет тестирование, и вы можете получить большую помощь в управлении графиком зависимостей, используя контейнер IOC.

Я могу сказать это, обжегшись на подобных вещах ранее :)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top