Entity Framework veritabanı bağlamını (model) MVVM WPF'de ViewModel'e bağlamanın en iyi yolu nedir?


9

Yukarıdaki soruda olduğu gibi: MVVM'de (WPF) viewModel'e Entity Framework veritabanı modelini (bağlam) bağlamak için en iyi yol nedir?

Ben WPF MVVM desen öğreniyorum, örnekler bir sürü viewModel model uygulamak gösterir, ancak bu örneklerde modeller sadece basit sınıflar, ben MVVM varlık çerçeve modeli (temel ilk yaklaşım) ile birlikte kullanmak istiyorum. Model modelini görüntülemek için en iyi yol nedir?

Cevaplarınız için teşekkürler.

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

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

Bu benim her zamanki ViewModel ctorum, daha iyi bir yol olduğunu düşünüyorum, depo deseni hakkında okuyordum, bunu WPF MVVM'ye uyarlayıp uyarlayamayacağımdan emin değilim

Yanıtlar:


4

Ben bunu biraz inceledim ve "mükemmel" bir çözüm bulamadım. Depo deseni, kısa ömürlü bir denetleyicide var olduğu için bağlamın kısa ömürlü olduğu MVC uygulamaları için harika çalışır, ancak aynı yapıyı VM'nin uzun süre devam edebileceği bir wpf uygulamasına uygulamaya çalıştığınızda sorun oluşur.

Geçmişte bu çözümü, çok fazla basit olan ve hata ayıklaması zor olan neredeyse okunamayan kod miktarlarına neden olan şeyleri aşırı miktarda soyutlamaya teşebbüs ettiğim birçok repo deseninden çok daha basit kullandım. İşte adımlar ...

  1. EDMX'in Veri erişim katmanınız olarak hareket etmesi için ayrı bir proje oluşturun
  2. Aynı proje altında bir "Depolar" klasörü oluşturun
  3. "İş Birimi" olarak hareket etmek için bir temel sınıf "BaseRepository" oluşturun. IDisposablebunu a using(){}ve partialdiğer depoları uygulamanıza izin verir.

    public partial class MyEntityRepository : IDisposable
    {
        MyEntities context = new MyEntities();
    
        public void Dispose()
        {
            context.Dispose();
        }
    }
  4. "MyOtherRepository" adlı başka bir dosya oluşturun. aynı kısmi sınıfı oluşturun ancak o dosyanın içermesini istediğiniz yöntemlere göre yöntemler uygulayın

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

Şimdi VM'nizde bunu yapabilirsiniz ...

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

Bu, tüm depolarınızı tek bir sınıfta gruplandırır, böylece ayrı bir bağlamla uğraşmanıza gerek kalmaz. Yöntemleri farklı dosyalara gruplayarak farklı depoları daha iyi yönetmenizi sağlar ve kod çoğaltmasını önlemeye yardımcı olur. Bunun da ötesinde, bağlamlarınız bu kalıbı kullanmadan olduğu kadar kısa ömürlüdür.

Dezavantajı, daha büyük sistemlerde, repo altında toplanan birçok yönteminiz olabilir. Bu durumda bir çözüm, "Bul" veya "Ekle" gibi bazı temel ortak komutları uygulamak ve özel depolarında uzman komutları uygulamak olacaktır.


2
'MyEntityRepository' EF'nin kendi içeriğini değiştirebilir ve aynı sonucu elde edersiniz. EF'in bağlamını kendi "havuzunuz" ile sarmak istemiyorsanız, çoğaltmayı artırın.
Euphoric

@Euphoric Evet yapabilirdiniz, ancak daha sonra deponun bağlam üzerinde kullanıldığı garanti edilmez. Bütün mesele EF'in basit iş gereksinimlerine nasıl çalıştığını
Shoe

4

Sevmediğim depolara karşıyım. Ayende'nin önerdiği gibi Command kalıbını kullanmanızı tavsiye ederim .

Basitçe söylemek gerekirse, her işlem için ayrı bir ThisOperationCommandsınıf oluşturursunuz. Bu sınıfın içinde normal EF bağlamıyla çalışacaksınız. Hatta EFCommandsizin için bazı sıhhi tesisat yapan bazı temel sınıflar bile kullanabilirsiniz .

ViewModel tarafından, bu komutun bir örneğini oluşturursunuz, parametrelerle doldurursunuz (komut ile ViewModel arasında sıkı bir bağlantının sakıncası yoksa tüm ViewModel örneğini bile geçebilirsiniz) ve sonra bunu Executebaşlatan bir tür yönteme geçirirsiniz. komutu çalıştırın, çalıştırın, yırtın ve sonra komutun sahip olduğu her şeyi döndürün. Ayrıca, yürütme işleminden sonra komut örneğinden alırsanız birden çok değer döndürmesini de sağlayabilirsiniz.

Avantajı, veri erişim katmanının tamamını depo olarak çoğaltmanız gerekmemesi ve onu desteklemek için basit bir altyapı oluşturduğunuz sürece komutları yeniden kullanabilir ve oluşturabilirsiniz. Örneğin, diğer komutlardan komutların yürütülmesi.


0

Basit senaryolar için aşağıdakileri kullandım:

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
Sorun şu ki, bağlamınız artık potansiyel olarak "uzun yaşam".
Ayakkabı

1
Sınıfın içindeki bağlamın örneğini oluşturmamalısınız, bunun yerine yapıcıya enjekte etmelisiniz.
Oscar Mederos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.