21

If I am generating POCO objects from EntityFramework, and using these to go to/from the WCF server, is there any reason to create client-side Models for the Views & ViewModels to use instead of just using the POCOs directly?

Almost all the MVVM examples I have looked at bind straight to the object returned from the WCF service. Is this good practice? Are there arguments that can be made for actually mapping the POCO to a Model and having the Views/ViewModels working with the Model object instead of the POCO?

The main reason I could think of is validation, however since the EF POCOs are partial classes, they can be expanded on to include validation.

EDIT

Most answers so far have brought up INotifyPropertyChanged as the main reason to build a separate Model. Does your answer change if you are using Self-Tracking entities instead of POCOs which already includes INotifyPropertyChanged? STEs are also partial classes which can be expanded upon to include validation.

Rachel
  • 122,023
  • 59
  • 287
  • 465
  • Self-tracking EF POCO's might be OK, but regular self-tracking Entites still expose the entire entity to the View. I think I'd rather have those stored in a private variable and map ViewModel properties to them as necessary (not exposing the entire Entity, just the parts I want to view and update. I don't know, maybe I'm making too much out of it. – Joel Cochran Apr 02 '11 at 16:28
  • 1
    OK, we were doing something similar in a WPF application to this over the weekend at Southern Maryland Give Camp. We used the Self-tracking entities T4 template to generate the POCO entity classes and exposed them through the service layer. In experimenting, I saw no reason to NOT use the POCOs directly. Rather than wrapping them, we created Partial class files to enhance them as needed. Worked great (with a few caveats like finally realizing that "Self-tracking" is not enabled by default on self-tracking entities). – Joel Cochran Apr 04 '11 at 14:15
  • Where are you doing your validation? Don't forget about INotifyDataErrorInfo on your Models (or ViewModels if you're in the Reed camp :D ) – SQLMason Apr 04 '11 at 19:33
  • 1
    If you're doing something quick and simple, and your Views don't demand too much from your objects, then sure just use them -- I do so a lot myself. However, since you'll never know when your views are going to be enhanced and made complicated -- that's the beauty of MVVM afterall -- you're best off creating good rich objects for anything significant used to bind to views. That's because you may not be the person writing views in the future and cursing on the way about the lack of features in the underlying objects. – Stephen Chung Apr 07 '11 at 06:01

5 Answers5

9

Validation is the main reason not to bind directly to a POCO. In addition, if the POCO doesn't already implement INotifyPropertyChanged and other required interfaces, the experience working with the object on the WPF side may be less desirable, and implementing a ViewModel to wrap this makes sense.

Providing a ViewModel to wrap your POCO allows you to encapsulate the logic into ICommand implementations as well as implement required interfaces cleanly.

Reed Copsey
  • 522,342
  • 70
  • 1,092
  • 1,340
  • @Rachel: They typically do - this needs to be pushed across the wire, which can happen, or not, depending on how you configure and create your WCF endpoints, though. They do not necesarily implement `INotifyCollectionChanged` or `IDataErrorInfo` or other interfaces (INPC was just one example) – Reed Copsey Mar 29 '11 at 17:03
  • 2
    @Reed So if I am understanding you right, you expose the POCO properties in the ViewModel instead of creating a separate Model for them? – Rachel Mar 29 '11 at 17:45
  • 3
    @Rachel: Yes, typically, I'd treat the POCOs coming across the wire as the "Model", and make a ViewModel to expose them to the View. That's pretty much the classic MVVM style. – Reed Copsey Mar 29 '11 at 17:47
  • @Reed OK, thanks. I was viewing it a little differently... I had the Model as a class of its own and the ViewModel exposed a property of type Model which could be bound to – Rachel Mar 29 '11 at 18:09
  • @Rachel: FYI - I go into this in quite a bit of detail in my blog (http://reedcopsey.com/series/windows-forms-to-mvvm/), particularly in the discussion of "The Model" as well as the MVVM summary here: http://reedcopsey.com/2010/01/06/better-user-and-developer-experiences-from-windows-forms-to-wpf-with-mvvm-part-7-mvvm/ – Reed Copsey Mar 29 '11 at 18:11
  • The ViewModel should have a collection of Models. You bind your View to your ViewModel. Your Models should have a way to become WCF Objects (POCO in this conversation). If you're doing Silverlight, you can't send INotifyDataErrorInfo across the wire which means your Business logic is on the other side of your WCF Service. – SQLMason Mar 29 '11 at 20:44
  • @Reed See my comment on @Dan Andrews answer below. Why would you prefer to do something like this over creating a client-side Model that implements `INotifyPropertyChange` and `IDataErrorInfo?` – Rachel Mar 30 '11 at 13:15
  • @Rachel: You disagree with Reed and then give him the bounty and right answer? – SQLMason Apr 08 '11 at 19:54
  • @Dan I asked this question because I did not know the answer. Since Reed's answer has the most votes, it usually means that the community agrees with this answer so I have accepted it. I have done some further research on the matter and you can really code your application either way. – Rachel Apr 08 '11 at 19:58
  • There really isn't a difference between Reed's method and the method I use. I just call my wrapped DTO's a model and he calls them ViewModels. He then has ViewModels which have ViewModels. The difference it moot. – SQLMason Dec 29 '11 at 17:39
  • Thanks @ReedCopsey. In my scenario, I prefer using POCOs, but along with that I also don't like re-writing my entity properties in the models, so I'm binding directly to the model provided by the VM. Is there a way to implement `INotifyDataErrorInfo` in the VM only? – Shimmy Weitzhandler Dec 05 '19 at 08:21
6

I disagree only slightly with Reed (an unusual circumstance to be sure). I would NOT implement a ViewModel to wrap the POCO. I would implement a Model class to wrap the POCO and expose the Models to the ViewModel via a Service layer.

The ViewModel's primary job is to appropriately present Model data to the View and react to its requests. The architecture I'm working on for this looks like so:

  • 1 ViewModel for each View
  • The ViewModel calls a Data Service layer object to retrieve Model instances (not to be confused with a WCF service)
  • The Data Service layer issues the appropriate CRUD requests to the backend (this uses WCF, RIA, or RESTful Services for Silverlight but could be ADO.NET or EF directly for WPF).
  • The Data Service uses the returned POCOs to create Model objects.
  • Model objects wrap the POCO object and implement INotifyPropertyChanged. Model objects enforce business rules.

I'm still working through the details but I will be publishing something more concrete in the near future.

Joel Cochran
  • 5,023
  • 2
  • 24
  • 35
  • @Joel Thanks, that is actually the route I have now although an argument has been brought up against it because of the additional coding and classes involved. It doesn't help that most of the MVVM examples out there just bind straight to the WCF object. – Rachel Mar 30 '11 at 15:33
  • yeah, I agree with you Joel. I like Reeds answers most of the time though. +1 from me as we all have a similar answer anyway. ;) – phillip Mar 30 '11 at 15:33
  • @Rachel it is extra coding no doubt but well worth it. I use CodeRush and it will expand your properties to include the INotifyPropertyChanged events automatically. One of the hundreds of time-saving features it contains. – phillip Mar 30 '11 at 15:37
  • It is a little more coding, but I think the long term benefits will outweigh the hassle. Most likely, with T4 templates we could find a way to simplify the process. – Joel Cochran Mar 30 '11 at 16:03
  • Your answer is similar to mine and you have +2.. I get no love :D – SQLMason Mar 30 '11 at 17:43
  • 1
    I mostly have 1 ViewModel per View, but sometimes I will have two different Views that display the same ViewModel in a different way (DataGrid and DataForm). I call by Data Service layer a Data Provider to prevent confusion – cadrell0 Mar 30 '11 at 17:49
  • @Joel You mentioned in another comment that you would make your POCO's Self-Tracking. If you did that, would you still build a separate Model layer? Self-tracking entities contain INotifyPropertyChanged, and since they are partial classes you could also build in Validation – Rachel Apr 01 '11 at 19:37
  • I added some comments to the original post. Having experimented some now I'm not sure that I would bother with creating a local Model class. I think the Self Tracking POCOs can be used just fine. As you mentioned, we used Partial classes to extend them as needed. (We were doing WPF, but with the same architecture I discussed above, so to the ViewModel it made no difference.) The only thing that sticks in my head is that the POCO still exposes the entire entity, which you may not want: it may not be a problem, but we'll see. – Joel Cochran Apr 04 '11 at 14:26
  • @Joel I see, thanks for sharing that. I agree that I don't like exposing the entire entity, however it does make coding faster without having to build that extra layer – Rachel Apr 05 '11 at 12:09
2

My Models accept a WCF object which exposes those properties which I wish to use in my ViewModel. I can then also extend the object as needed. My properties point to the WCF object's property and when I have to send the object back to the WCF service, I don't have to do any more work. The models inherit INotifyPropertyChanged and INotifyDataErrorInfo which the DTOs (mentioned here as POCOs) will not have. Your business logic / validaton exists in your Silverlight application and not in your WCF Service.

The View binds to the ViewModel which has a Model (or an observable collection of Models). The Models have a WFCObject which is a DTO (mentioned here as POCO). I use my ViewModel to communicate with the service, MVVM Light has the models communicate with the service / provider - which I don't like.

SQLMason
  • 3,190
  • 1
  • 27
  • 39
  • I like this idea, although I am doing Model Validation on both the Client and Server side – Rachel Mar 30 '11 at 13:06
  • Does anyone know why Reed's answer is preferred over something like this? To me it doesn't quite make sense since like he said, the WCF objects do not contain `INotifiyPropertyChanged` or `IDataErrorInfo` and if the same model were used in multiple views I feel that you would end up repeating a lot of extra code to expose the WCF object's properties in the ViewModel – Rachel Mar 30 '11 at 13:14
  • I don't know. The reason why I did it this way was so that I don't have to copy objects WCF.Name = Model.Name etc, etc, etc. And I wouldn't have two in memory as well. You can do validation on both sides and I've done that once because of a shared WCF Service - I didn't want someone sneaking in crap through my DAL. – SQLMason Mar 30 '11 at 13:48
  • 2
    This is fine - however, this "Model", in a classic MVVM sense, is technically a VM. You're wrapping the DTO (which is, really, the Model) to provide validation, etc. – Reed Copsey Mar 30 '11 at 14:41
  • 1
    @Reed I would disagree. The Model isn't a ViewModel, because it doesn't interact with any kind of View or contain any data that would be bound to a View. It only contains data relevant to the data object – Rachel Mar 30 '11 at 15:34
  • @Rachel: You're specifically making a class that implements interfaces required for data binding, and wrapping your DTO. That's nothing but a basic ViewModel. The ViewModel, in MVVM, doesn't "interact" with the View - it should be the other way around. The ViewModel is used *by the View*, and should be "passive" in terms of UI interaction for the most part. – Reed Copsey Mar 30 '11 at 15:48
  • @Reed: For me, the ViewModel contains collections of Models, governs and directs the Models (handles the WCF service). I would never bind to my Model directly which is as you imply. Could you explain: "The ViewModel, in MVVM, doesn't 'interact' with the View - it should be the other way around." – SQLMason Mar 30 '11 at 17:21
  • 3
    @Reed: I disagree. While INotifyPropertyChanged and IDataErrorInfo are used by the View, they have other uses as well. I handle PropertyChanged events regularly to trigger some action. The ViewModel has things for the View to interfact with like Commands and PagedCollectionViews. – cadrell0 Mar 30 '11 at 17:46
0

Rachel's POCO's are just dumb objects generated by EF and used for transport (DTO). Therefore, they shouldn't have other things cluttering up their domain. This is a very nice way of designing your code because it decouples any client-side requirements from those on the server-side. That's why MVVM exists - to extend the MVC model incorporating those concerns.

There is no reason you can't bind to them in your views as long as you are not modifying them directly. You can add functionality to them by adding a partial class but I wouldn't even do that. In that case you should follow the MVVM design tenants and separate those into model objects that serve your needs in the client. This will be quite automated once you hook up INotifyPropertyChanged events to notify your views.

phillip
  • 2,400
  • 15
  • 21
  • I've not used MVVM, I think in MVC. Is `they shouldn't have other things cluttering up their model` appropriate only to MVVM? What about business logic? Or is that widely regarded as belonging in Domain objects that are not used as Models? – StuperUser Mar 29 '11 at 17:13
  • 1
    @StuperUser: Not cluttering up the Model really applies to ALL architectural patterns, whether MVVM, MVC, MVP, or other. – Reed Copsey Mar 29 '11 at 18:12
  • 1
    @grrr: POCOs are classified as "dumb" because they shouldn't contain anything other then properties and their getters/setters. The reason why they are ideal for going to/from a WCF service is they are small and lightweight when going across the wire. – Rachel Mar 29 '11 at 18:26
  • 1
    I think this answer confuses a POCO with a DTO or similar – Jack Ukleja Mar 29 '11 at 22:55
  • @grrrrrrr Did you even read her question? She is sending the POCO which makes it a DTO as well. A POCO is supposed to be dumb - in that it shouldn't contain business logic. See wikipedia http://en.wikipedia.org/wiki/Plain_Old_CLR_Object : POCOs are objects unencumbered with inheritance or attributes. If you are adding more to them then you don't have a POCO, you have a business object. – phillip Mar 30 '11 at 05:31
  • Yes I am using the POCOs like DTOs since EF will auto-generate them for me and I don't have to hand-code them. – Rachel Mar 30 '11 at 13:39
  • 1
    I don't see why this answer is voted down: @philip is absolutely correct. Especially in the case of EF POCOs (I'd make them self-tracking) transferred via WCF, the POCO is just a transport mechanism. The business layer should consume it and modify it as needed (CRUD), applying the business rules to it. Of course, this is all IMHO. – Joel Cochran Mar 30 '11 at 15:17
0

Bind to EF POCOs if you want to do simple CRUD or you want to make something fast.

Otherwise, your server-side models will tend to be very closely related to the database, which changes very slowly, as compared to user interface. For less trivial UI, you'll find yourself putting more and more kludges just to fit your database model into UI (or otherwise, which is even worse).

Also, there are performance issues (e.g. would you like to transmit whole entity when for UI you need only couple of properties?), and maintenance issues (e.g. if you would like to validate premium customer's order quite differently from ordinary one).

See also http://ayende.com/Blog/archive/2010/08/06/data-access-is-contextual-a-generic-approach-will-fail.aspx

ovolko
  • 2,697
  • 2
  • 21
  • 26