Який найкращий спосіб підключити контекст (модель) бази даних Entity Framework до ViewModel в MVVM WPF?


9

Як і в запитанні вище: Який найкращий спосіб підключити модель бази даних Entity Framework (контекст) для перегляду Моделі в MVVM (WPF)?

Я вивчаю шаблон MVVM у WPF, багато прикладів показує, як реалізувати модель для viewModel, але моделі в цих прикладах - це просто прості класи, я хочу використовувати MVVM разом із сутнісною каркасною моделлю (базовий перший підхід). Що найкращий спосіб підключити модель для перегляду моделей.

Дякую за відповіді.

//ctor of ViewModel 
public ViewModel()
{ 
db = new PackageShipmentDBEntities(); // Entity Framework generated class

ListaZBazy = new ObservableCollection<Pack>(db.Packs.Where(w => w.IsSent == false)); 
}

Це мій звичайний переглядач ViewModel, думаю, є кращий спосіб, я читав про шаблон сховища, не впевнений, чи зможу я адаптувати це до WPF MVVM

Відповіді:


4

Я вивчив це зовсім небагато і не знайшов "ідеального" рішення. Шаблон сховища чудово працює для програм MVC, де контекст недовговічний, оскільки він існує в короткочасному контролері, але проблема трапляється, коли ви намагаєтесь застосувати ту саму структуру до програми wpf, де VM може зберігатися протягом тривалого періоду часу.

У минулому я використовував це рішення, яке набагато простіше, ніж багато репо-шаблонів, які я бачив, намагаючись абстрагувати речі до крайньої кількості, в результаті чого майже не читаються кількості коду, які важко налагодити. Ось етапи ...

  1. Створіть окремий проект, щоб EDMX виступав як ваш рівень доступу до даних
  2. Створіть папку "Репозиторії" під тим самим проектом
  3. Створіть базовий клас "BaseRepository", щоб діяти як "одиниця роботи". IDisposableдозволить вам використовувати це в a, using(){}а partialволя дозволить вам реалізувати інші сховища

    public partial class MyEntityRepository : IDisposable
    {
        MyEntities context = new MyEntities();
    
        public void Dispose()
        {
            context.Dispose();
        }
    }
    
  4. Створіть ще один файл під назвою "MyOtherRepository". створити той самий частковий клас, але реалізувати методи на основі того, що ви хочете, щоб цей файл містив

    public partial class MyEntityRepository
    {
        public void MyOtherMethodSave(EntityObject obj)
        {
            //work with context
            ...
    
            context.SaveChanges();
        }
    }
    

Тепер у своєму віртуальному комп'ютері ви можете це зробити ...

using(MyEntityRepository repo = new MyEntityRepository())
{
     repo.MyOtherMethodSave(objectToSave);
}

Це об'єднує всі ваші сховища в одному класі, тому вам не доведеться мати справу з окремим контекстом. Це дозволяє краще керувати різними репозиціями шляхом групування методів у різні файли та запобігає дублюванню коду. Крім того, ваші контексти такі ж недовговічні, як і раніше, без використання цього шаблону.

Недоліком є ​​те, що у великих системах у вас може бути безліч методів, які підпадають під ваш репо. Одним з рішень у цьому випадку буде реалізація деяких основних загальних команд, таких як "Знайти" або "Додати", та впровадити спеціалізовані у відповідне сховище.


2
Ви можете замінити власний контекст EF "MyEntityRepository" EF і отримаєте такий же результат. Якщо ви не хочете обгорнути контекст EF своїм власним "сховищем", збільшуючи дублювання.
Ейфорія

@Euphoric Так, ви могли б, але тоді вам не гарантується, що сховище буде використано в контексті. Вся справа в тому, щоб відмовитися від того, як EF працює на прості бізнес-вимоги
взуття

4

Протилежний сховищам, які мені не подобаються. Я рекомендував би використовувати шаблон Command, як рекомендує Ayende .

Простіше кажучи, для кожної операції ви створюєте окремий ThisOperationCommandклас. Всередині цього класу ви будете працювати в нормальному контексті EF. Ви можете навіть використовувати якийсь базовий клас, EFCommandякий робить сантехніка для вас.

З боку ViewModel ви створюєте екземпляр цієї команди, заповнюєте її параметрами (ви навіть можете передавати цілий екземпляр ViewModel, якщо ви не заперечуєте про щільне з'єднання між командою та ViewModel), а потім передаєте її якомусь Executeметоду, який запуститься. виконайте команду, виконайте її, зірвіть її та поверніть все, що отримала команда. Ви також можете його повернути кілька значень, якщо ви отримаєте його з екземпляра команди після виконання.

Перевага полягає в тому, що вам не потрібно дублювати весь рівень доступу до даних як резосторій, і ви можете повторно використовувати та складати команди, поки ви створите просту інфраструктуру для її підтримки. Наприклад, виконання команд з інших команд.


0

Для простих сценаріїв я використовував наступне:

public class ViewModel : IDisposable {

    private EntitiesContext _context = new EntitiesContext();

    private SomeEntity _model;
    public SomeEntity Model {
       get { return _model; }
    }

    public View(int id) {
        _model = _context.SomeEntity.Find(id);
    }

    private ICommand _saveCommand = new RelayCommand(() => _context.SaveChanges());
    public ICommand SaveCommand {
        get { return _saveCommand; }
    }        

    public void Dispose() {
         _context.Dispose();
    }

}

1
Проблема в цьому полягає в тому, що зараз ваш контекст потенційно "довго живе".
взуття

1
Ви не повинні створювати екземпляр контексту всередині класу, а вводити його в конструктор.
Оскар Медерос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.