I am building a ASP.NET MVC application where I use the following flow :
Get Entity
Run Action at a controller
Fetch data from FactoryClass that operates against the Model(Entity Framework)
Get data back to the Action in the controller
Use AutoMapper to translate from Model object to ModelView object
Return the ModelView object to the strongly typed View
Update Entity
Run Action with ModelView Entity as input (DefaultDataBinder will be used)
Validate ModelView Entity
Send the ModelView object direcly to the right factory method.
Check if the ModelView object has id and if so fetch the Model object from database
Use AutoMapper to translate the incoming ModelView object to a Model object/entity. If its a update, then use the fetched Model object as destination.
If it is a update use Refresh Client.Wins else use Add
Run SaveChanges and return to the controler.
Problem 1
The ModelView classes is special made for the views that the controler actions is connected to (it could contain both edeting objects and lists). It´s common that several actions with diffrent views uses the same ModelView Class, that means that not all objects in the ModelView object will be used in every action/view.
As long as the View uses all the properties of ModelViewObjects that can be updated there is no problem but...
Say that we got a View where some of the properties of the ModelViewObject is not used, this ModelViewObject is sent to the factory(to be updated) where the corsponding ModelObject is fetched(from db/entity framework) and then merged with the ModelViewObject with AutoMapper. The problem here is that properties on the ModelViewObject that is not set(not used in the view) will result in a overwrite of real data in the ModelObject.
To solve this u usually use AutoMapper ForMember Ignor(), but this will be a problem when a complete ModelViewObject(all properties set) will update db.
How do you handle this? Do you have diffrent Update methods in the factorys where diffrent AutoMapper setting?
It would be nice If I could only have a method like this : UpdateMyEnityt(MyEntity entity) and this methid will update och add MyEntity object.
Problem 2
Where should I place the AutoMapper mappings? So far I have placed Updates in the factory and Get in the controller. I have thought of placeing the mappings in the ModelViewObject for example ModelViewObject.ToDataModel but if I do not need a complete translate(som properties is to be ignored) then I will have to do this AutoMapper else where.
How do you handle this?
Problem 3
Say that you have an working update method in our factory class where you use AutoMapper with som ignors to translate a ModelViewObject to a ModelView(entity framework object). Say now that we updates the database table with a new field/propertie, if we run a view that handles the ModelViewObject corsponding to this tabel but do not handle the new propertie this will mean that the propertie will always be set to null/string.empty/0. When running the regular update method in the factory there will not be a ignor on this propertie and this means that the zero value will overrite the real value.
Its a big risk that these kind of updates will be done and its a big risk that I will not remember to handle this in old code.
How do I handle this?
Problem 4
AutoMapper have a validation method where you can check if the mappings will be possible, right now I am having these validations where the mapping is done, should I maby put this in some other method where the validation will be executed as fast as the application starts? Else problems in the mappings will show first when using the function.
BestRegards
At first you should use viewModel for each view. And fetch only date that you need.
You should add facility to manual mapping for "difficult" issue.
I thing that AutoMapper is wrong way for transfer date from Db object to View Object.
Problem 1: If you are using a different View, use a different ViewModel. This way only the properties that are displayed will be automapped.
Problem 2: Different Automapper Settings in each project with
Project1.AutomapperSettings.Execute();
Project2.AutomapperSettings.Execute();
etc
in the Global.asax or similar entry point.
Problem 3: See problem 1
Problem 4: Use ValidationAttribute on viewmodel properties and let mvc take care of it
Related
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.
I have an EDM used to bring back a collection of "Product" entities within a DAL project. An MVC website project references and directly instantiates the ObjectContext and returns an IQueryable to the website for paging and displaying of Products.
This Entity, to simplify things, we'll say only has "ID", "Rate" and "Description" properties. I want to create another calculated property called "CostPerMonth" which will take an input from the website called "LoanAmount", and, again, to keep things simple, this "CostPerMonth" property will be made up of (("LoanAmount" * "Rate") / 12).
I can't help but feel this calculation should be done in the DAL project to make the code more reusable, as whereever this data is used, a "LoanAmount" will always be specified. The possible solutions I have had are below:
Create a partial class for Product, add a new property "CostPerMonth" to Product. In the website controller, when the data is returned, populate this new column by iterating through the returned data and doing the calculations?
Create a partial class for Product, add a new property "CostPerMonth" to Product. In the DAL project, create a helper class that has a method that accepts a "LoanAmount" parameter and returns a List. The trouble with this is I would need to materialize the data in order to do the calculations. The method could accept a "Skip" and "Take" parameter that could be used in the Linq query used to return the products?
Create a partial class for Product, add a new property "CostPerMonth" to Product. Add another tier to the solution using WCF web services, within the service method do the calculations and use REST to return the data to the MVC web site?
Any advice would be very much appreciated.
Best regards,
Mark
If we take a step back and actually breakdown what you are asking in your question it might be easier to explain my answer.
We have an object/entity named Products
There is a calculated field which will be (("LoanAmount" * "Rate") / 12)
CostPerMonth does not need to be stored in the database
So this calculated field is a business rule for the Product Entity. Given that you are using MVC, there is only one place where this code/logic can go and that is the model.
Given that your using EF It will sit in a non mapped/computed field and the code to give you an idea will look something like this....
[NotMapped]
public decimal CostPerMonth
{
get { return (LoanAmount * Rate)/12 ; }
}
I can go on for days about the problems about having fragmented business logic throughout various layers.
Now if you want your this logic to be consumed easily by other clients, you need to expose a service to do that. (you can use webAPI/service stack/ wcf, etc) it is really another entire question based on your needs. But the point here is that your logic is in one spot.
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.
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.
I have a design question related to Entity Framework entities.
I have created the following entity:
public class SomeEntity {
// full review details here
}
This entity has as an example 30 columns. When I need to create a new entity this works great. I have all of the required fields in order to insert into the database.
I have a few places in my app where I need to display some tabular data with some of the fields from SomeEntity, but I don't need all 30 columns, maybe only 2 or 3 columns.
Do I create an entirely new entity that has only the fields I need (which maps to the same table as SomeEntity, but only retrieves the column I want?)
Or does it make more sense to create a domain class (like PartialEntity) and write a query like this:
var partialObjects = from e in db.SomeEntities
select new PartialEntity { Column1 = e.Column1, Column2 = e.Column2 };
I am not sure what the appropriate way to do this type of thing. Is it a bad idea to have two entities that map to the same table/columns? I would never actually need the ability to create a PartialEntity and save it to the database, because it wouldn't have all of the fields that are required.
Your first approach is not possible. EF doesn't support multiple entities mapped to the same table (except some special cases like TPH inheritance or table splitting).
The second case is common scenario. You will create view model for your UI and either project your entity to view model directly in query (it will pass from DB only columns you project) or you will query whole entity and make conversion to view model in your application code (for example by AutoMapper as #Fernando mentioned).
If you are using EDMX file for mapping (I guess you don't because you mentioned ef-code-first) you can use third approach which takes part from both mentioned approaches. That approach defines QueryView - it is EF based view on the mapped entity which behaves as a new read only entity. Generally it is reusable projection stored directly in mapping.
What you proposed as a first solution is the "View model paradigm", where you create a class for the sole purpose of being the model of a view to retrieve data and then map it to the model class. You can use AutoMapper to map the values. Here's an article on how to apply this.
You could create a generic property filter method that takes in an object instance, and you pass in a string array of column names, and this method would return a dynamic object with only the columns you want.
I think it would add unnecessary complexity to your model to add a second entity based on the same data structure. I honestly don't see the problem in having a single entity for updating\editing\viewing. If you insist on separating the access to SomeEntity, you could have a database view: i.e. SomeEntityView, and create a separate entity based on that.