3

I have a Prototype using WPF + MVVM + PRISM + ENTITY FRAMEWORK

The problem is that im very confuse if i use the ENTITY FRAMEWORK Entities as the Model of the MVVM pattern. I have a Business Logic Layer, and i had problems using mappers on this layer, because im very unhappy on the conversion (Map problem).

What i can do to simplify the code, use a real Model not the Entitie object(for me use the Entitie as model is incorrect on the frontend), with the MVVM pattern on mind... and stay good for changes on the future, it will have 200+ entities on the final version...

Thats my layers...(Please forget about Mapping, since i taked it off putting the EF entities on the ViewModel, but the image represents the correct layers)

Im not using the repository too since i can add it on the end with changes only on the BLL.

My layers

VIEW MODEL: my current prototype do a getall, put it on a grid, and on selectchanged of the grid i put selected item on the textbox, and the save button update this changes to the database.

public class CadastroClienteViewModel : BindableBase, ICadastroClienteViewModel
{
    private readonly IClienteBLL _clienteService;

    #region Model
    //public Cliente ObCliente { get; private set; }

    public int ClienteID
    {
        get { return ((Cliente)cliItems.CurrentItem).ClienteID; }
        set
        {
            ((Cliente)cliItems.CurrentItem).ClienteID = value;
            OnPropertyChanged("ClienteID");
        }
    }

    public string Nome
    {
        get { return ((Cliente)cliItems.CurrentItem).Nome; }
        set
        {
            ((Cliente)cliItems.CurrentItem).Nome = value;
            OnPropertyChanged("Nome");
        }
    }

    #endregion

    public CadastroClienteViewModel(IClienteBLL ServiceCliente)
    {
        //ObCliente = new Cliente();
        _clienteService = ServiceCliente;

        this.SaveCommand = new DelegateCommand(ExecuteMethodSave);
        this.RefreshCommand = new DelegateCommand(ExecuteMethodRefresh, CanExecuteMethodRefresh);
        RefreshCommand.Execute(null);
    }

    private void ExecuteMethodSave()
    {
        _clienteService.ClienteBLL_Update(((Cliente)cliItems.CurrentItem));

        RefreshCommand.Execute(null);
    }

    private bool CanExecuteMethodRefresh()
    {
        return true;
    }

    private void ExecuteMethodRefresh()
    {
        var personViewModels = _clienteService.ClienteBLL_GetAll();

        //cliente = new ObservableCollection<Cliente>(personViewModels);

        cliItems = new ListCollectionView(personViewModels.ToList());
        cliItems.CurrentChanged += CliItemsOnCurrentChanged;

        //OnPropertyChanged("cliente");
        OnPropertyChanged("cliItems");
    }

    private void CliItemsOnCurrentChanged(object sender, EventArgs eventArgs)
    {
        //OnPropertyChanged("ObCliente");
    }

    public ICommand SaveCommand { get; private set; }
    public ICommand RefreshCommand { get; private set; }

    //public ObservableCollection<Cliente> cliente { get; private set; }
    public ICollectionView cliItems { get; private set; }
}

MODEL(Im not using it... but i would like):

public class MCliente
{
    public int ClienteID { get; set; }
    public string Nome { get; set; }
}

EF Entitie:

namespace Sistema.DataEntities.Models
{
public class Cliente
{
    public Cliente()
    {
    }

    public int ClienteID { get; set; }

    public string Nome { get; set; }
}

BLL:

public class ClienteBLL : IClienteBLL
{
    readonly ISistemaContext _context;
    public ClienteBLL(ISistemaContext context)
    {
        _context = context;
    }

    public IEnumerable<Cliente> ClienteBLL_GetAll()
    {
        return _context.Cliente.AsEnumerable();
    }

    public Cliente ClienteBLL_GetByID(int id)
    {
        return _context.Cliente.Find(id);
    }

    public bool ClienteBLL_Adicionar(Cliente Obcliente)
    {
        _context.Cliente.Add(Obcliente);
        return _context.SaveChanges() > 0;
    }

    public bool ClienteBLL_Update(Cliente Obcliente)
    {
        _context.Cliente.Attach(Obcliente);
        _context.Entry(Obcliente).State = EntityState.Modified;
        return _context.SaveChanges() > 0;
    }

    public bool ClienteBLL_Delete(int id)
    {
        var clubMember = _context.Cliente.Find(id);
        _context.Cliente.Remove(clubMember);
        return _context.SaveChanges() > 0;
    }
Community
  • 1
  • 1
Danilo Breda
  • 1,092
  • 1
  • 15
  • 30
  • If you don't have your extra layer of models then you don't have to map back and forth, if you do have it then what exactly what does it give you? – Ben Robinson Sep 08 '14 at 14:42
  • Update problems on the entity framework... Internal Exceptions... http://stackoverflow.com/questions/25454801/icollectionview-throw-entity-framework-attach-exception – Danilo Breda Sep 08 '14 at 14:46
  • I don't really see how an extra layer of models would help with that. – Ben Robinson Sep 08 '14 at 14:48
  • Take the EF Entities and put it on the ViewModel is OK? its sounds very strange for me thats why... – Danilo Breda Sep 08 '14 at 14:50
  • Why not do it, your explanation implies a set of identical classes that you map back and forth between your EF models. What purpose would this serve? – Ben Robinson Sep 08 '14 at 14:54
  • 1
    Using EF entities as viewmodels is fine, given the entities are all pocos. You can merge the Model and Business Layer as one since, Model should have the logic and orchestrate the business logic. The models can still work with your viewmodels and to save I'd call some service or some repository so that models don't know about database details. – AD.Net Sep 08 '14 at 15:01
  • Yeah... I think you are right.. the purpose is very singular... but like this example i dont know how to handle the viewmodel EF Entitie as the model... if you help me as aswer with a example or a edit on my code it would be great. – Danilo Breda Sep 08 '14 at 15:03

1 Answers1

4

I'm adding this as an answer (not a comment) even if it's not a final answer to your question (cause it's opinion-based) but it doesn't fit as a comment. That's just what I would do for a WPF application that requires a database.

I would entirely drop the idea of directly connecting your WPF application to your database. I would build a 3-tiers architecture, i.e. I would create a stateless webservice that does all the stuff on server side.

So you would have:

  • the database
  • the webservice (using WCF), that is connected to the database, that does all the data stuff for you (I would even make it responsible of the business stuff too)
  • the WPF application, that is connected to the webservice:
    • the View layer is your XAML + your code-behind
    • the ViewModel layer is, well, your ViewModels (out of scope of your question, but feel free to ask if you have any question about that layer). The ViewModels asynchronously call the webservice
    • the Model is the client WCF proxy

Some benefits of this approach:

  • depending on the hardware/network harchitecture, could be a huge performance benefit to only make ONE call to the server instead of N calls (assuming the latency between the DB and the webservice (both on "server side") is lower than the one between the WPF application and the database)
  • more scalable
  • all benefits of the stateless approach: one Entity Framework context instantiation per webservice requests, so much easier to deal with concurrency issues (in case you have N WPF instances running concurrently)
  • easier to maintain (loose coupling between tiers)
  • easier to test (assuming you actually build tests)
  • better security (no need to expose a direct access to the database over the network)
ken2k
  • 48,145
  • 10
  • 116
  • 176
  • but if the customer need the database to stay on the intranet... can i host the WCF service on a local server, thats recomended? And if i use the WCF and the Direct Database connection too thats possible? Some customers have only 1 computer... with low memory... WCF is not good for it i think. – Danilo Breda Sep 09 '14 at 04:01