Как избежать использования большого количества dbcontexts в .NET с использованием MVVM? - PullRequest
0 голосов
/ 23 мая 2018

Я пытался научиться создавать веб-приложения в .NET, используя MVVM-шаблон.Я смотрел некоторые учебные пособия, и есть одна вещь, которую я не понимаю.

Каждый ViewModel содержит:

public class IndexModel : PageModel
{
    private readonly ApplicationDbContext _dbContext;

    public IndexModel(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    ..
}

Хорошо скопировать, вставить это, когда у вас есть пара страниц(максимум 10), но мое приложение начинает расти и начинает чувствовать себя очень избыточно, используя этот метод.

Мне не удалось найти другое сообщение, отвечающее на мой вопрос, но мне интересно, есть ли какой-либо другой способ использования _dbContext на каждой модели ViewModel без использования этой избыточности?Я не очень знаком с шаблонами проектирования, но будет ли вариант синглтона в моем стартапе вариант?

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Это не шаблоны дизайна звука.Что вы можете сделать, это передать бизнес-интерфейс вашей модели представления как внедренную зависимость, используя внедрение зависимости ( Unity пример).Затем эта внедренная бизнес-служба может внедрить в нее интерфейс службы данных, в котором находится контекст данных.

Считать плохой уровень данных на уровне презентации считается плохой практикой.Вот пример способа разделения слоев кода.

Ниже приведен простой пример IDataService (обратите внимание, что я имею дело только с интерфейсами, а контекст данных остается в службе данных):

public class DataService : ServiceBase, IDataService
{
    public DataService(IMapper mapper) : base(mapper) { }

    public IList<UserDto> GetUsers(bool runSafeMode = true)
    {
        Func<IList<UserDto>> action = () =>
        {
            return GetUsers(_ => true);
        };

        return ExecutorHandler(action, runSafeMode);
    }

    ...

    private IList<UserDto> GetUsers(Expression<Func<User, bool>> predicate, bool runSafeMode = true)
    {
        Func<IList<UserDto>> action = () =>
        {
            using (var ymse = YMSEntities.Create())
            {
                var users = ymse.User
                    .Include(u => u.UserUserProfile)
                    .Include(m => m.UserUserProfile.Select(uup => uup.UserProfile))
                    .Include(m => m.UserUserProfile.Select(uup => uup.User))
                    .Include(m => m.UserUserProfile.Select(uup => uup.UserProfile.UserProfileModule))
                    .Where(predicate).OrderBy(u => u.UserName).ToList();

                return MappingEngine.Map<IList<UserDto>>(users);
            }
        };

        return ExecutorHandler(action, runSafeMode);
    }
}

Это внедряется в бизнес-сервис, который, в свою очередь, внедряется в мою виртуальную машину:

public class DocksViewModel : ViewModelBase
{
    public DocksViewModel(IConfigService configService, IEventService eventService, INotificationService notificationService)
    {
        ...
    }
}

Простое разделение задач, и все проверяется независимо.Мой IDataService в этом случае находится в BaseViewModel, потому что в зависимости от того, имеет ли мое приложение подключение к Интернету или нет, я переключаю реализации между сервером sql и локальными файлами json для сохранения данных.Вот как вы можете связать свои зависимости, используя Unity, например:

        var unityContainer = new UnityContainer();

        ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(unityContainer));

        unityContainer.RegisterType<IServiceLocator, UnityServiceLocator>(new ContainerControlledLifetimeManager());

        // automapper
        var config = new MapperConfiguration(cfg =>
           cfg.AddProfile(new AutoMapperBootstrap())
       );

        unityContainer.RegisterType<IMapper>(new InjectionFactory(_ => config.CreateMapper()));

        // factories
        unityContainer.RegisterType<IWelcomeGateViewFactory, WelcomeGateViewFactory>();
        unityContainer.RegisterType<ITrailerPictureViewFactory, TrailerPictureViewFactory>();

        // services
        unityContainer.RegisterType<IDataService, OfflineDataService>("OfflineDataService", new ContainerControlledLifetimeManager(), new InjectionConstructor(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ServiceLocator.Current.GetInstance<IMapper>()));
        unityContainer.RegisterType<IDataService, DataService>(new ContainerControlledLifetimeManager());
        unityContainer.RegisterType<ITestDataService, TestDataService>(new ContainerControlledLifetimeManager()); 

        ...
0 голосов
/ 23 мая 2018

Добавить пользовательский базовый класс, унаследованный от PageModel.Затем унаследуйте всю свою модель от своего пользовательского базового класса.

public abstract class MyBasePageModel : PageModel
{
   protected readonly ApplicationDbContext _dbContext;
   public MyBaseModel(ApplicationDbContext dbContext)
   {
      _dbContext = dbContext;
   }
}


public class IndexModel : MyBasePageModel 
{
    public IndexModel(ApplicationDbContext dbContext):base(dbContext)
    {
      // 
    }
}
...