MVVM design feels too unwieldy, am I doing it wrong? - c#

I've recently started creating a WPF application, and am just hoping that someone can confirm to me that I'm building my overall system architecture properly, or correct me if I'm heading off in the wrong direction somewhere. Especially since I'm trying to do MVVM, there are a lot of layers involved, and I'm not sure I'm doing things properly.
Here's a simplified description of the system:
Data is stored in an SQL Server database, which is accessed through Linq to SQL. Let's say that the database contains two tables, USERS and USER_GROUPS. Each table has an auto-generated Linq to SQL class, DB_USER and DB_USER_GROUP.
Now in the application, I want to display a ListBox with each ListBoxItem containing various UI elements for displaying/modifying the users' info, which is done using a DataTemplate.
I have a view model class for the window, which uses a Linq to SQL query (joining the two tables) to populate an ObservableCollection<User> named UserList, which the ListBox in the window has bound as its ItemsSource. User is a class implementing INotifyPropertyChanged that handles all the formatting/getting/setting of database data into what's needed by the WPF controls. The section of code handling this is something like:
DBDataContext db = new DBDataContext();
var allUsers = from user in db.USERs
.Where(u => u.ENABLED == true)
from group in db.USER_GROUPs
.Where(g => g.GROUPID == u.GROUPID)
.DefaultIfEmpty()
select new { user, group };
foreach (var user in allUsers)
{
User u = new User(db, user.user, user.group);
UserList.Add(u);
}
So the User class is constructed with private properties for a DB_USER, a DB_USER_GROUP, and the database DataContext class. All of a User's public properties basically wrap the relevant columns, with their get methods returning the values for WPF to use, and set changing the column(s) and then calling SubmitChanges() on the private DataContext property to update the database.
This is all working fine, but it feels a little unwieldy, so I'm just wondering if I've missed something that would make it cleaner. Specifically, storing a DataContext inside each element of UserList seems odd, but I wasn't sure of a better method to be able to update the database whenever data was changed in the UI.
Any feedback is appreciated, and please let me know if anything's unclear, I'm not sure how well I've explained it.

Starting off, let's put some labels on what you are doing here: DB_USER is your Model and User is your ViewModel (I 'd have preferred UserViewModel for the latter just so that it's more clear what's going on).
One thing that's immediately obvious is that it's not really proper for your ViewModel to have functionality suited to your Model, i.e. that DataContext does not belong where it currently is. This is a piece of information that should either be in your Model, or alternatively encapsulated in some DataStore/DataService (take your pick) class. Your ViewModel would then be responsible, when the time comes to save any changes, to tell the DataStore "here's an updated snapshot of this model, please save it for me" (this would most likely be exposed to the UI through an ICommand). This feels cleaner and underscores the idea that your ViewModel is a layer that adapts the realities of your model to your choice of UI.
Other than the above, there's nothing in what you describe that I feel needs to be "corrected". However, I can offer some suggestions regarding things that you have not elaborated on.
Exposing data from a Model through a ViewModel is always something that can be implemented in many ways. When considering what approach to take, you should take into account the possibility of the same Model being exposed through different Views at the same time. In this case, IMHO the preferred approach is to have a separate ViewModel for each View (the Views may well be of different types, so they could have different expectations from the ViewModel adapter thus pointing to multiple types of ViewModels as well), so you would need to use a pattern that allows changes to be communicated from one ViewModel to any others in "real time".
One way to do this would be to make your Models implement INotifyPropertyChanged themselves and have each ViewModel hook into its Model for notifications, so when a change occurs ViewModel A pushes the change to the Model, and the Model notifies ViewModel B.
However personally I don't like polluting my Models with what is in essence code that only caters to the needs of the UI, so another approach is needed. That would be making the DataService I mentioned above expose functionality (methods and events) through which ViewModel A can tell the service "hey, the Model I 'm wrapping has had some changes" ; note that this is different from "I want you to persist the current snapshot of this Model". ViewModel B has already hooked into a suitable "ModelChanged" event, so it gets notified and pulls the updated information from the service. This has the added benefit that if at any time the service detects that the backing data repository has been updated by a source external to the current process, there's a ready made mechanism to broadcast a "Calling all ViewModels: Model X has been updated, any interested parties please talk to me about learning the details" message.
Above all, always keep in mind that there is no "one true MVVM style" and there are myriads of possible approaches. Which one to take depends not only on hard facts and the current position of the slider on the YAGNI/HyperEngineering scale, but also on, dare I say, your taste.

Tricky question, and I can see why people aren't jumping all over themselves to answer—mainly because you aren't doing anything technically wrong. But since you ask, I'll tell you what I'd change to tighten up both MVVM (which you asked for) and the data acess (which you didn't).
The way I approach a ViewModel is as a wrapper for my underlying data model, rather than as an enhancement to my View. It assists the view by providing INotifyPropertyChanged and all that, but I try to make the ViewModel useful for whatever view it'll end up inside. That's the main difference, IMO, between MVC and MVVM. What you have is more of an MVC with your User object acting as a controller for the View.
Also, I'd probably do away with UserList and use the ListBox.ItemsSource to manage the list after binding it once. Actually, in WPF, I've gotten more used to having a CollectionViewSource and binding the UI controls to that. Makes it simpler to track selected items and adding to them and removing from them isn't too onerous.
For the data access, I wouldn't feed those into the object at all. Data access belongs in your model and persisting changes should be handled there. The .Net framework does a pretty good job with connection management, to the point where re-instantiation and teardown are the next best thing to costless. That allows you to keep things tight and wrap data connections in using clauses. If you really feel like you have to persist to the database on every property change, have your model subscribe to the PropertyChanged event—that's what it's there for, after all. :)

Usually, I keep my models as dumb as possible (POCO). My viewmodel has the heavy logic of querying the database and setting its properties that are bound to the UI. In that layout, the viewmodel has a single instance of your DataContext and there is no need for it to be passed around inside of the models.

I generally follow that approach with some differences, big surprise there :) In larger projects I don't like to wrap or include my domain entities in my ViewModels. This is something I carried over from the ASP.NET MVC in Action books where you map (AutoMapper) domain entities to display models before the view receives them. Its nice when there is an impedance between the domain entity(s) and what needs to be displayed.
It also comes in handy when mocking up the screens, I can work from the screen backwards to the DisplayModel knowing I'll map what I need from the domain entity. I'm big on my Views being blendable so a designer can open the View up and it looks pretty close to run time View.
So in some cases I'll have my entity models (User/UserGroup), my DisplayModel (User), and my ViewModel (UserViewModel).
As mentioned in other answers I tend to keep the data business out of the ViewModel. I'll create a Repositiory or a service of some type and inject it into my ViewModels. So in my ViewModel I might call var user = UserRepository.GetUsers(); and then map the results to my DisplayModel. Or UerRepository.InsertOrUpdate(user); UserRepository.Save();
Unrelated, AutoMapper is a great tool as well as Caliburn Micro or MVVM-Light.

Related

Using CQRS with repositories

If I understand correctly CQRS is about dividing write and read responsibilities. So I can use repositories in my write model, for example var user = repository.GetUserById(); - this will get the user by id and then repository.UpdateUser(user); will update the user with changed properties. In the read model we can construct more complex DTO's:
public class UsersReadModel
{
private IMyContext context;
public UsersReadModel(IMyContext context)
{
this.context = context;
}
public ComplexUserDTO GetComplexUser(ISelectQuery query)
{
ComplexUserDTO user = new ComplexUserDTO();
// get all user properties, GetUser by id
user.UserDTO = context.Users.Where(d => d.UserId == query.UserId).ProjectTo<UserDTO>().FirstOrDefault();
//here I don't need everything from PoliciesTable, I just need two columns, so I use anonymous object
var policieObject = context.Policies.Where(f => f.BasePolicyId == query.PolicyId).Select(s => new { s.PoliciesNames, s.Clients.Select(d => d.ClientNames).ToList() }).FirstOrDefault();
user.PoliciesNames = policieObject.PoliciesNames;
user.ClientsNames = policieObject.ClientsNames;
return user;
}
}
So in my Write model, I get user by id from my repository, because i don't need to map it to DTO, and in my read model I use GetUser by id, but I map it to DTO, because I need it in that way. Isn't this code repeat(if I want to change getting user by id i'll have to change it in both places)? Can I use repositories in my read model? In this case I'll have to use both repositories and context(for the anonymous object, and selecting part of table columns) in UsersReadModel.
If your domain is very simple then the Write and the Read will be very similar and a lot of cod duplication will occur. In fact, this works in reverse as well, if your Write model is very similar to the Read model then you could implement them as CRUD and you don't necessarily need CQRS.
Can I use repositories in my read model?
You can have anything you want on the Read side; the two sides are separated from many points of view.
In CQRS there are many cases when code duplication occurs. Don't be afraid of that. You could extract that in shared classes.
P.S.
You should have a Read model for every use case, not for every Write model. If you have a 1:1 correspondence from Write to Read then this could also means that you should have implemented this using CRUD.
P.S. I like to use CQRS even if the domain is simple as I like to have very optimized Read models (different persistence type, no JOINS, custom data sharding etc).
There are a few things to look at here. From your description, it doesn't sound like there is a separation between the read and write models. Remember, they have very different purposes.
CQRS leans heavily on domain-driven design principles. A key principle is the encapsulation of your domain objects.
As a result, you wouldn't expect a domain object to have 'properties' on it (especially not setters). It may have ID for example but not much else. This is becuase it's role is to protect invariants within its self. Not something you can do easily if you have setters.
I would also argue that a domain object shouldn't really have getters except for id. If you have a good read model there is little need for them and may encourage incorrect use of the object. There are times when this idea can be relaxed a little. Although I can't think of one right now.
As a result, a repository for a domain object can be very simple. GetById and Save (unless you are using event sourcing but that's another topic).
The Read model, on the other hand, should be shaped to serve the UI. Each model is likely to have a mix of data from various sources. For example, you are likely to want to see a users details in context or their activities or orders or value to the company or whatever the purpose of the application is.
This explanation of the typical structure of a CQRS application may be helpful: CQRS + Event Sourcing - A Step by Step Overview
And this may give you some insight into creating domain objects: Aggregate Root - How to Build One for CQRS and Event Sourcing
Hope this helps.
If I understand correctly CQRS is about dividing write and read responsibilities.
Closer to say that it is about having data models that are designed for the use cases that they support.
We have Truth, and that truth has multiple representations.
The trick is that the representations don't need to be coupled in time -- we can update the "book of record" representation now, and the representations we use to support queries eventually.
Can I use repositories in my read model?
Absolutely. There's no magic.
Udi Dahan would probably suggest that you be thinking about different repositories, or perhaps more precisely methods on your repositories that provide different explicit representations of the read model depending on what you are doing. Each method loads the representation that you need for that particular use case.

Do I make viewmodels for each page?

I'm creating a game where I have a lot of different pages. For instance: loginpage, profilepage, playersfriendeditpage.
Do I create a ViewModel for each of them? They are all dealing with the model, "player", but in diffeent aspect. Whats common sense?
Well since a view model acts as interface to your model from your view, it makes sense that any time a view needs to modify a model differently than any other view has, you'll want a new view model.
In other words, even though various views may LOOK different, it's the interaction with the model/view model that dictates whether a new view model is necessary.
If your page contains a ton of stuff, it may make sense to break them up into sub VMs. I try to think of a ViewModel as just a class and like any other class, you don't want it to do EVERYTHING if it doesn't make sense to. If your page is logically broken up into a mini-views, then you should be able to easy encompass those needs in a sub-VM.
For example: say you have an edit page that contains all your info. Maybe the user information (name, address, phone #) is a VM, the work history is a VM and the hobbies section is a VM and your main VM basically does all of the stuff around it. You can use messaging and/or events to handle the communication needs.
ViewModels are useful when you want to create a model that contains an instance of another model. This is the case when you have a 1 to many relationship between one model and another (one table and another) and need to display both information on the same view, for example. Or not even 1 to many necessarily, but that's often the case.
If you have a drop down list that contains values populated from a table in a database, but your View should display all other information from a different model, for example, you would use a ViewModel in this example.
I would define a ViewModel as an abstraction of a view. The viewModel should contain properties and methods which provide the Data and behaviour that a view requires to function correctly.
Given this definition my instinct would be to provide a separate viewModel for each view as they are each likely to have their own unique behaviour.
The fact that all views depend on the same Player entity is an implementation detail and as has already been suggested this functionality should be moved into a base class that the other viewModels can derive from, something along the lines of this:
public abstract class ScreenViewModel : ViewModelBase // Implements INotifyPropertyChanged
{
private Player _currentPlayer;
public ScreenViewModel(IRepository<Player> playerRepository)
{
// Retrieve desired player from the repository.
this._currentPlayer = playerRepository.Find(...);
}
// This is an idea of the sort of thing you can do; derived viewModels
// do not need to worry about loading the player, they can just consume
// it and provide the screen specific behaviour.
protected Player CurrentPlayer
{
get { return _currentPlayer; }
}
}
I don't agree with the advice provided in the currently accepted answer as it is wrong; it is your views that should shape your viewModels not your database. The design of the database should have little or no bearing on the design of your viewModels. The whole point of having a viewModel between your view and your domain layer is to insulate your application from changes in the lower layers.
In fact, if you look at the example viewModel I have provided it is fairly well insulated from those sorts of changes. The Player would typically be exposed as a POCO (making it persistence ignorant) and the repository that provides access to those entities is hidden behind an interface.
This means I could change the way the database structure is implemented and these changes would be absorbed by the data layer (e.g. by changing the way Entity Framework maps the tables to the entities in the application) and the viewModel would require no changes. You could even change the persistence mechanism (I.E. save data to a custom file rather than a database) and as long as it mapped the data to the Player POCO and the new repository implemented the IRepository<Player> interface your viewModel would still work as expected, demonstrating that the database structure has little or no bearing on the design of your viewModels.
It depends on the way you design your database.
If you want all the fields to be in a same table you can keep them under the same view model and this is not the case with most of the cases because you wouldn't like to have any redundant information in your database and you want your database to be normalized. So you can structure your models depending on your database design so that your database has no redundant information.

ASP.NET MVC3 update only necessary fields

Suppose we have class PersonModel, user edits a detail form in the browser and hits the submit button.
How to write a controller logic to create an UPDATE SqlComand (no EF) and update only those of fields from class PersonModel (FirstName, LastName, Age...) which have been changed.
What should be an argument of the /Person/Edit/<id> controller?
You don't do anything special to your MVC code, and you don't add any special URL parameters.
If you only want to update the changed fields, then you have to write a lot of code. You have to get the current record, compare each of your models fields to the records fields, figure out which ones have changed, then you have to construct a SQL statement based on the changed fields, then update it, making sure to use optomistic record locking to insure the field has not changed between when you retrieved it and when you update it.
This is probably going to be a couple hundred lines of code. Or it could be one line of code if you were using an ORM.
Also, keep in mind you need to use parameterized statements as well, to insure against a SQL injection attack (something you get for free in an ORM as well).
Good luck, I certainly am not going to write it.
What I would suggest is that you don't use the generalized PersonModel which I assume is a 1:1 representation of your data model. You should create a watered down view model of with only the fields you care about. Then use something like AutoMapper to map the ViewModel back to your DomainModel.
Here is a reference on how to use AutoMapper for such a scenario.
How to cross map objects using AutoMapper
You may use Linq and let the datacontext do everything for you.
In the Model you just create your data class with the linq queries for the update, retrieve the object, set all the values that have been passed from the view in the object you've retrieved (you'll have to do this anyway, since the pattern decouples the view from the model | Remember too, that MVC implements observer for letting the view to know about changes in the model, so you can't know what was modified in the view from the controller), and then you call the DataContext.SubmitChanges(); method. The data context will do the job in its own. It will know what to change and modify and will make the most performant query.

Most productive way to use ViewModels, Data Annotation based validation and Domain Objects?

I am using NHibernate for persistence and have my domain model mapped out. I am using MVC2 and I am keen to use the built in model validation for all basic validation (string length, range, etc).
The problem is that I'm finding that there is a huge amount of work involved in this. I have 26 POCO classes representing the domain. Which means I need roughly 5 x 26 = 130 ViewModels (one for create, edit, view, list, delete) given I'm going to use ViewModels everywhere. 130 ViewModels to create and maintain considering I have my domain objects already mapped out seems wasteful.
Now I've bought into the idea that this is a good way to develop as a way to keep the view as dumb as possible, eliminate view related security blunders, etc. To be honest I get the strong impression I'm missing a tool or technique that would speed this process up.
Is there a way to reduce this pain?
I'm not sure why you would need 5 ViewModels? The ViewModels kinda represent what you want to display (in the view):
Lets say you have these Related Entities:
BlogArticle
Tags
CategoryName
You have three entities but from the form that creates the BlogArticle you're writing the article, selecting tags and then choosing a category on one page.
On the BlogArticle create form you just want the following ViewModel:
BlogArticleViewModel
+string BlogTitle
+string BlogContent
+string TagName //could be mapped to textbox, checkbox
+string CategoryName//same as above
You could use http://automapper.codeplex.com to map Models to ViewModels.

What do you name the "other" kind of view-model in an MVVM project?

With MVVM, I think of a view-model as a class that provides all the data and commands that a view needs to bind to.
But what happens when I have a database entity object, say a Customer, and I want to build a class that shapes or flattens the Customer class for use in a data grid. For example, maybe this special Customer object would have a property TotalOrders, which is actually calculated using a join with a collection of Order entities.
My question is, what do I call this special Customer class? In other situations, I'd be tempted to call it a CustomerViewModel, but I feel like "overloading" the notion of a view-model like this would be confusing in an MVVM project. What would you suggest?
I believe you were correct in your original thoughts. The "View Model" classes are those that expose data objects in the domain Model such that these model objects are more easily consumed and managed.
Check out http://en.wikipedia.org/wiki/Model_View_ViewModel
Therefore, the Customer and Order classes are pieces of the "Model". What you describe and were considering calling the CustomerViewModel is indeed a "View Model" and then obviously your WPF page/control is the "View".
In terms of naming it... Go with whatever you like! But I like your original idea of CustomerViewModel. Or perhaps name it a little closer to that of the View. For example, CustomerOrderSummaryViewModel if the page is the CustomerOrderSummary page.
We call ours Data View Models.
For example, we may have Results.xaml that has the Results_ViewModel as the view model. The results page has a grid, where each row in the grid is a Customer. But, like you said, you want a view model for the customer so that you can have a property like 'Total Orders.' In this case, our grid would contain a collection of Customer_DataViewModel.
This comes up quite frequently where is some examples you have a List objects that aren't quite view models. Since you are changing the Customer model object into something more for the VM, you could name it CustomerDto or I agree with the rest of the posters, CustomerViewModel (CustomerVM) is fine too.
I do not like the CustomerDto as it implies another concept (ie. something representing data to be sent elsewhere). We use the term PresentationModel as it is basically 'presenting' an underlying model object with properties that do not belong in the model-layer. For me, I use the term ViewModel for when I can actually change the model and PresentationModel for read-only views.

Categories