I'm currently writing my first MVVM application which uses EntityFramework for data access.
The Application relies heavly on the underlying database and has to add new Data to the DB in many cases.
However, I'm uncertain about whether or not it is a good idea to call the ObjectContext inside the ViewModel.
e.g.
public class SomeViewModel : ViewModelBase
{
public IEnumerable<User> AllUsers { get; private set; }
private void SomeMethod()
{
var __entities = new DatabaseEntities();
AllUsers = __entities.Users.Where(...).ToList();
}
}
I've seen solutions like this, but there are some question coming along with it.
For example how long the ObjectContext actually lives, or if one should prefer a single, global accessable ObjectContext.
Or should calls like those not be part of the VM in the first place?
Currently I can also imagine to implement like StaticHelpers for each DB table and use Methods like GetAllUsers().
In Josh Smith's sample Application about MVVM he uses a Repository thats injected in the Constructor of each VM.
public AllCustomersViewModel(CustomerRepository customerRepository)
Despite the fact that this has to be a common issue, I found no satisfying answer on how this issue is approached for smaller applications (best practice)?
In the descripton of the DbContext class on MSDN it states "Represents a combination of the Unit-Of-Work and Repository patterns", so it can act as your Repository layer, although it doesn't have to, and it is intended to be used for a "Unit of Work" which doesn't fit using a global one for the entire app. Besides keeping a single one around for everything could cause issues with cached data and other undesirable things (memory usage, etc...).
Hope this helps.
Related
I have a WPF application with MVVM. Assuming object composition from the ViewModel down looks as follows:
MainViewModel
OrderManager
OrderRepository
EFContext
AnotherRepository
EFContext
UserManager
UserRepository
EFContext
My original approach was to inject dependencies (from the ViewModelLocator) into my View Model using .InCallScope() on the EFContext and .InTransientScope() for everything else. This results in being able to perform a "business transaction" across multiple business layer objects (Managers) that eventually underneath shared the same Entity Framework Context. I would simply Commit() said context at the end for a Unit of Work type scenario.
This worked as intended until I realized that I don't want long living Entity Framework contexts at the View Model level, data integrity issues across multiple operations described HERE. I want to do something similar to my web projects where I use .InRequestScope() for my Entity Framework context. In my desktop application I will define a unit of work which will serve as a business transaction if you will, typically it will wrap everything within a button click or similar event/command. It seems that using Ninject's ActivationBlock can do this for me.
internal static class Global
{
public static ActivationBlock GetNinjectUoW()
{
//assume that NinjectSingleton is a static reference to the kernel configured with the necessary modules/bindings
return new ActivationBlock(NinjectSingleton.Instance.Kernel);
}
}
In my code I intend to use it as such:
//Inside a method that is raised by a WPF Button Command ...
using (ActivationBlock uow = Global.GetNinjectUoW())
{
OrderManager orderManager = uow.Get<OrderManager>();
UserManager userManager = uow.Get<UserManager>();
Order order = orderManager.GetById(1);
UserManager.AddOrder(order);
....
UserManager.SaveChanges();
}
Questions:
To me this seems to replicate the way I do business on the web, is there anything inherently wrong with this approach that I've missed?
Am I understanding correctly that all .Get<> calls using the activation block will produce "singletons" local to that block? What I mean is no matter how many times I ask for an OrderManager, it'll always give me the same one within the block. If OrderManager and UserManager compose the same repository underneath (say SpecialRepository), both will point to the same instance of the repository, and obviously all repositories underneath share the same instance of the Entity Framework context.
Both questions can be answered with yes:
Yes - this is service location which you shouldn't do
Yes you understand it correctly
A proper unit-of-work scope, implemented in Ninject.Extensions.UnitOfWork, solves this problem.
Setup:
_kernel.Bind<IService>().To<Service>().InUnitOfWorkScope();
Usage:
using(UnitOfWorkScope.Create()){
// resolves, async/await, manual TPL ops, etc
}
my first real (not test) NHibernate/Castle.ActiveRecord project is developing quickly.
I am working with NHibernate/Castle.ActiveRecord about one month now but still have not a real idea how to handle Sessions in my WindowsForms application.
The common handling-methods seam not to work for me:
SessionPerRequest, SessionPerConversation, etc. all only work for WebApplications, etc.
SessionPerApplication is not recomanded/highly dangerous when I am correct
SessionPerThread is not very helpfull, since I either have only one thread, the WindowsForms-thread, or for each button-click a new thread. The first thing would make my applicaton use too much memory and to hold old objects in the memmory. With worker-threads for ech button click I would disable lazy-loading, since my loaded objects would live longer then the thread.
SessionPerPresenter is not working as well, because it is common, that I open a "sub-presenter" in a form to let the user search/load/select some referenced objects (foreigen key) and of cause the presenter is destroyed - what means session closed - but the object used in the "super-presenter" to fill the referencing property (foreigen key).
I've used google and bing for hours and read a lot, but only found one good website about my case: http://msdn.microsoft.com/en-us/magazine/ee819139.aspx . There SessionPerPresenter is used, but to a "sub-presenter" it is only given the id, not the entire object! And it seams that there are no foreigen-keys in this example and no scenari in wich a object is returned to a "super-presenter".
Qestions
Is there any other method of session handling for windowsforms/desktop-application?
I could add a session-property or a session-constructor-parameter to all of my presenters, but it feels not right to have session-handling all over my ui-code.
When an Exception occures NHibernate want's me to kill the session. But if it is 'only' a business-logic exception and not an NHibernate-Exception?
Example
I am trying to make an example the covers most of my problem.
// The persisten classes
public class Box
{
public virtual int BoxId{get;set;}
public virtual Product Content{get;set;}
...
}
public class User
{
public virtual int UserId{get;set;}
public virtual IList<Product> AssigenedProducts{get;set;}
...
}
public clas Product
{
public virtual int ProductId{get;set;}
public virtual string PrductCode{get;set;}
}
.
// The presenter-classes
public class ProductSearchPresenter : SearchPresenter<Product> { ... }
public class ProductEditPresenter : EditPresenter<Product> { ... }
public class UserSearchPresenter : SearchPresenter<User> { ... }
public class UserEditPresenter : EditPresenter<User> { ... }
public class BoxSearchPresenter : SearchPresenter<Box> { ... }
public class BoxEditPresenter : EditPresenter<Box> { ... }
// The search-presenters allow the user to perform as search with criterias on the class defined as generic argument and to select one of the results
// The edit-presenters allow to edit a new or loaded (and given as parameter) object of the class defined as generic argument
Now I have the following use-cases, wich all can be performed in the same application at the same time asyncronous (the use simply switchs between the presenters).
using an instance of BoxSearchPresenter to search and select a object
part of this usecase is to use an instance of the ProductSearchPresenter to fill a criteria of the BoxSearchPresenter
part of this usecase is to use an instance of the BoxEditPresenter to edit and save the selected object of the BoxSearchPresenter-instance
using an instance of UserSearchPresenter to search and select a object
part of this usecase is to use an instance of the UserEditPresenter to edit and save the slected object of the UserSearchPresenter
part of this usecase is to use a ProductSearchPresenter to search and select objects that will be added to User.AssignedProducts.
Using an instance of ProductSearchPresenter to search and select a object.
part of this usecase is to use an instance of ProductEditPresenter to edit and save a selected object of the ProductSearchPresenter.
It's only a small collection of usecases, but there are allready a lot of the problems I have.
UseCase 1. and 2. run at the same time in the same ui-thread.
UseCase 1.1. and 2.2. return there selected objects to other presenters that use this objects longer then the presenters exist that have loaded the object.
UseCase 3.1. might alter a object loaded from 2.2./1.1. before 3.1. was started, but when 2.2./1.1. is commited before 3.1. is finished the object would be saved and it would not be possible to "rollback" 3.1.
Here is just a short view of what I found best to fit into our WinForms application architecture (based on MVP).
Every presenter is constructor dependent on repositories which it needs, for example if you have InvoicePresenter then you have InvoiceRepository as dependency, but you will probably have CustomerRepository and many others depending on complexity (CustomerRepsitory for loading all customers into the customers combobox if you want to change customer of the invoice, stuff like that).
Then, every repository has a constuctor argument for UnitOfWork. Either you can abstract the session with UnitOfWork pattern, or you can have your reporitories depend on ISession.
Everything is wired together by IoC container, where we create presenters based on "context". This is a very simple concept, context is per presenter and all sub presenter, which in turn we create as composite block of more complex presenters to reduce complexitiy (if for example you have multiple tabs of options to edit some entity or something).
So, in practice, this context is 90% time form based, because one form is at least one presenter / view.
So to answer your questions:
Session per presenter and session per conversation (works with WinForms as well) are only really usable patterns here (and opening closing sessions all over the place, but not really good way to handle that)-
this is best solved by making repositories depend on session, not presenters. You make presenters depend on repositories, repositories depend on session, and when you create all, you give them common session; but as I state again, this is only practical when done in contexts. You cannot share session for presenter editing invoices and another presenter editing customers; but you can share session when editing invoice via main presenter and invoice details and invoice notes sub presenter.
Please clarify, didn't understand this...
I was just about to implement IDataErrorInfo, when I saw INotifyDataErrorInfo was to be used for asynchronous validation. When digging a bit further, I noticed the examples using those interfaces were all on the ViewModel. I need my validation on the model, and I need the errors stored with the model for persistence. I have a large graph with many entities. This graph needs to be passed back to the server for a complex validation. I'm not sure what approach I am supposed to use now.
Do I simply move my inteface implementations to the model?
Another example I saw had a separate validation service. In my case, my validation rules are complex, and I was thinking of using Windows Workflow and its rule engine to improve the maintainability of the validation rules.
Do I need a separate validation service?
Once the validation has completed, the graph must be passed back to the client. Any errors/warnings need to be displayed then.
Should I implement INotifyDataErrors in the model and raise the event when the validation returns to the client to post the errors to the View (through ViewModel)?
As it turns out, I am having trouble referencing the assembly that contains INotifyDataErrors in the class library. It creates a conflict in an assembly that is sharing those classes.
When you have big projects RIA may not be a good idea, for example applications with different layers (Services, Application, Domain, Infrastructure).
Some time ago I had to implement Validation in a Silverlight app with complex rules. I was using Self-tracking entities generated with the Entity Framework. And one of my need was to rehuse all the validation code.
First I tried to use the EntLib Validation Block and use the same code on both the client and the server. This approach doesn't work as you get some problems as SL and .NET4.0 use different versions of the DataAnnotations assembly.
Finally I ended up writing some sort of validation service on the server that returns the errors of an entity if any. Something like this:
interface IValidate
{
IEnumerable<string> Validate(Entity entity);
}
And then on the Client make the ViewModels implement INotifyDataErrorInfo (this interface supports async validation), so you can validate the entity with the Service and save the errors on the ViewModel.
class SomeViewModel : INotifyDataErrorInfo
{
public Entity Entity { get; set; }
public void Validate()
{
this.ClearErrors();
// this method make the service calls
var service = -- service instance --;
var errors = -- get errors from service --;
foreach (string error in errors)
this.AddTopLevelError(error);
}
{...}
}
This way all the validation logic lies on the Server and it can change at any time without affecting the client, because all the entities are passed througth this service before being added to a DataBase (if you're using one).
The service could also return the errors and the property associated with the error, this way you could get a richer interaction with Silverlight. So the service could be:
interface IValidate
{
IEnumerable<PropertyError> Validate(Entity entity);
}
class PropertyError
{
public string PropertyName { get; }
public IEnumerable<string> Errors { get; }
}
Here you can notice that the validation rules could change on the server, and it doesn't matter how this logic is implemented. All this works fine and meets your requeriments, the problem is that Silverlight requires that the object being validated contains all the properties with errors.
This is not a common scenario when working with Databases, as you could have for example (and this is a simple model)
this model was done using Entity Framework 4.1
Because if you have a user instance and want to access to the Email property, you'll have to type: user_instance.Person.Email. So the Email property isn't in the user type, and here is the problem with this solution because you may want to validate the EMails too.
Is this wasn't like this, when you have a ViewModel (implementing INotifyDataErrorInfo) with an Entity (like above) and wants the entity (User in this case) to be validated, you only have to add an error to the property Entity.Person.Email.
But the world isn't perfect, so the solution i found was to duplicate each one of the properties to be validated on the ViewModel, something like this:
class SomeViewModel : INotifyDataErrorInfo
{
public User Entity { get; set; }
public string Name { get { return Entity.UserName; } set {...} }
public string Email { get { return Entity.Person.Email; } set {...} }
{...}
}
This way you can bind the controls to the ViewModels properties instead of the entities properties, but it gets a bit hard to work with the change notifications.
You may also want to check: this toolkit. It solves this problem defining a wapper to your entity and using DynamicObject simulates an object that has all the properties from the wrapped one. This is a bit slow when working with large ammounts of data, but simplifies the work a lot.
Hope this helps.
It seems that ViewModels that I make look suspiciously like other classes and they seem to require a lot of code repetition, e.g. in a current project I have:
SmartForm: Model that represents a data form to fill in, has properties:
IdCode
Title
Description
collection of SmartFormFields
etc.
SmartFormControlView View
SmartFormControlViewModel ViewModel
IdCode
Title
Description
collection of SmartFormFields
etc.
So my ViewModel is basically the same as my Model, just with all the OnPropertyChanged features for binding with the View.
It seems as I refactor and extend this that every little change I make to my model, I have to make a mirror change to the ViewModel.
This seems to violate a basic rule of patterns Don't Repeat Yourself.
Am I implementing the MVVM pattern incorrectly or is it just an inherent characteristic of MVVM that there is always a 1-to-1 repetition going on between Model and ViewModel?
I personally don't think it violates DRY since the model and view-model (I prefer the term presenter) don't point to the same information. For instance your VM and M both have a Title property, but your VM's Title property could also include validation, whereas your model's Title property could assume validity.
While it's true that The VM may contain all of the properties of the model, there is also the possibility of having validations (e.g. Title must be non-blank), data-dependencies, bindable UI-specific properties (icons, colors, brushes, etc.) which aren't part of the view.
Essentially all UI patterns have similar "duplication" in the way you state it: namely cascading modifications. Try changing a model in MVC without changing the controller.
That being said, MVVM (or any UI pattern designed to separate UI, logic, and state) can be overly tedious for simple cases such as your example. When logic becomes little more than state-pass through, the value separating the controller/presenter/view-model decreases.
In your specific case, if there really isn't any logic, validation, or UI specific properties that your VM isn't surfacing, and your model doesn't have to be persisted, serialized, or made backwards compatible with an existing structure (or adding the logic to do so in your VM is trivial), I would strongly consider combining the M and VM to avoid creating properties whose sole purpose is to get/set the underlying model's properties.
A simple solution is to have an abstract ViewModel(VM) base class that exposes the model. You can choose this VM in scenarios where it makes sense.
i.e.
public abstract class ViewModelBase<T>
{
public T Model { get; set; }
}
If you Model has INotifyPropertyChanged implemented your view will get the event. What this does do is give your View access to every property in your Model which isn't what you want some times.
also you can utilize property initializers like this(which I personally have stored in code snippets):
public abstract class SampleViewModel
{
public int MyProperty
{
get { return Model.MyProperty; }
set
{
Model.MyProperty = value;
OnPropertyChanged("MyProperty");
}
}
}
In most circumstances you view will be the one making changes to your VM and when it does any control that is bound to that property will then be told that something happened.
Hope that helps.
That's an interesting remark... indeed, it's often necessary to modify the ViewModel to reflect the changes in the Model.
It would be nice if it could be automatic... actually I think it could be possible, by implementing ICustomTypeDescriptor in the ViewModel : GetProperties would return all the properties of the model through reflection. However I'm not sure it would make sense, because the model may not consist of properties at all : it could be methods, fields, or anything, and not everything in the model would be useful in the ViewModel.
One thing that seems to have been missed here and that your simplistic example does not expose is the fact that your Views will often aggregate data that is contained within multiple Domain Model types. In this case your ViewModels will contain references to a number of domain Models (of differing types) thus aggregating a bunch of related data that a particular View may wish to expose.
Others have provided good comments on the roles of the components of the MVC/MVVM patterns. I would like to offer a fundamental observation explaining the repetitiveness no matter which pattern you select.
Generally there will be some sort of repetition between your data layer, business layer and UI layer. After all, in general you have to show each property to the end user (UI), model it's behavior (Business layer) and persist the value (data layer).
As others have pointed out, the property might be treated a bit differently on each layer which explains the fundamental need for some duplication.
When working on systems large enough (or on small projects with the right team), I tend to model this type of information in UML, and use code generation (often coupled with partial classes) to handle the repetitive aspects. As a simple example, the Last Name property might have a requirement (in my UML model) that it limit data to 50 characters. I can generate code to enforce that limit into my UI layer (e.g. by physically limiting input), generate code into my business layer to recheck that limitation ("never trust the UI") by perhaps throwing an Exception if the data is too long, and generate my persistence layer (e.g. NVARCHAR(50) column, appropriate ORM mapping file, etc.).
2012 Update
Microsoft's Data Annotations and their support in the UI layer (e.g. ASP.Net MVC) and on the data layer (Entity Framework) goes a long way toward implementing many of the concerns I previously generated code for.
Eric Evans, in his book "Domain Driven Design" mentions that Model refactoring should not be too hard, and that a concept change should not span into too many modules, otherwise, refactoring the Model becomes prohibitive, so, if you ask me, having the Model sort of 'copied' in the ViewModel certainly difficults Model refactoring.
Eric mentions that one should give more weight to Model cohesion and isolation, than to a tidiness in the division of layers based on technical concerns (database access, POCOS, presentation). That the most important concern is that the Domain Model is a good representation of the Business Domain, hence its the most important for the Domain Model to be in a single isolated layer, and not spanned in several modules, in order for it to be easily updated (refactored).
Considering what was just said, I'd use the same Model object in the ViewModel, and if I want to reduce the level of "access" to a Model object, then I'd "pass" a reference to an Interface implemented by the Model object. For example:
// The primary Model classes
public partial class OrderItem {
public int Id { get; }
public int Quantity { get; set; }
public Product Item { get; set; }
public int Total { get; set; }
public void ApplyDiscount(Coupon coupon) {
// implementation here
}
}
public partial class Product {
public int Id { get; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}
// The shared views of those model classes
public partial class OrderItem : IOrderItemDTO {
public IProductDTO Item {
get {
return this.product;
}
}
}
public partial class Product : IProductDTO {
}
// Separate interfaces...
// You enforce the rules about how the model can be
// used in the View-ViewModel, without having to rewrite
// all the setters and getters.
public interface IOrderItemDTO {
int Id { get; }
int Quantity { get; set; }
IProductDTO Item { get; }
int Total { get; }
}
public interface IProductDTO {
string Name { get; }
string Description { get; }
decimal Price { get; }
}
// The viewmodel...
public class OrderItemViewModel {
IOrderItemDTO Model { get; set; }
}
I only know MVC and in MVC a Model-Class which contains GUI is some error. SmartForm seems to be a Form, which means it is not a model. I don't know what you are trying to program but I give you an example for a Model:
Take a Calender. You can ask the Class what date it is today, what month, how many days each month has, ...
It has no graphical representation though. The View (CalenderViewMonth or whater you want) prints a single Month on screen. It knows a Calender and asks him what to write in the different cells.
Essentially - you might have something wrong in your modeling / understanding of MVVM (which is a modern .NET-Variant of MVC).
Edit:
I just looked up MVVM on Wikipedia. Model is just like the Model in MVC. View like the View in MVC as well - only graphical representation. the ViewModel is the Glue between a generic View and a specialized Model. Some kind of Adapter. There should be no violation of DRY.
I think that yes, vanilla MVVM does violate DRY. But I've started the PDX library which I think can solve this problem in many cases. I wrote this post which I believe addresses this question.
Basically, my goal (one of them) is to have Viewmodels that don't worry about UI Notification. The PDX project is still in its infancy but if you're reading this question you might find it useful, and I would appreciate any feedback you may have.
Currently for ASP.Net stuff I use a request model where a context is created per request (Only when needed) and is disposed of at the end of that request. I've found this to be a good balance between not having to do the old Using per query model and not having a context around forever. Now the problem is that in WPF, I don't know of anything that could be used like the request model. Right now it looks like its to keep the same context forever (Which can be a nightmare) or go back to the annoying Using per query model that is a huge pain. I haven't seen a good answer on this yet.
My first thought was to have an Open and Close (Or whatever name) situation where the top level method being called (Say an event handling method like Something_Click) would "open" the context and "close" it at the end. Since I don't have anything on the UI project aware of the context (All queries are contained in methods on partial classes that "extend" the generated entity classes effectively creating a pseudo layer between the entities and the UI), this seems like it would make the entity layer dependent on the UI layer.
Really at a loss since I'm not hugely familiar with state programming.
Addition:
I've read up on using threads, but the
problem I have with a context just
sitting around is error and recovery.
Say I have a form that updates user
information and there's an error. The
user form will now display the changes
to the user object in the context
which is good since it makes a better
user experience not to have to retype
all the changes.
Now what if the user decides to go to
another form. Those changes are still
in the context. At this point I'm
stuck with either an incorrect User
object in the context or I have to get
the UI to tell the Context to reset
that user. I suppose that's not
horrible (A reload method on the user
class?) but I don't know if that
really solves the issue.
Have you thought about trying a unit of work? I had a similar issue where I essentially needed to be able to open and close a context without exposing my EF context. I think we're using different architectures (I'm using an IoC container and repository layer), so I have to cut up this code a bit to show it to you. I hope it helps.
First, when it comes to that "Something_Click" method, I'd have code that looked something like:
using (var unitOfWork = container.Resolve<IUnitOfWork>){
// do a bunch of stuff to multiple repositories,
// all which will share the same context from the unit of work
if (isError == false)
unitOfWork.Commit();
}
In each of my repositories, I'd have to check to see if I was in a unit of work. If I was, I'd use the unit of work's context. If not, I'd have to instantiate my own context. So in each repository, I'd have code that went something like:
if (UnitOfWork.Current != null)
{
return UnitOfWork.Current.ObjectContext;
}
else
{
return container.Resolve<Entities>();
}
So what about that UnitOfWork? Not much there. I had to cut out some comments and code, so don't take this class as working completely, but... here you go:
public class UnitOfWork : IUnitOfWork
{
private static LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("UnitOfWork");
private Entities entities;
public UnitOfWork(Entities entities)
{
this.entities = entities;
Thread.SetData(slot, this);
}
public Entities ObjectContext
{
get
{
return this.Entities;
}
}
public static IUnitOfWork Current
{
get { return (UnitOfWork)Thread.GetData(slot); }
}
public void Commit()
{
this.Entities.SaveChanges();
}
public void Dispose()
{
entities.Dispose();
Thread.SetData(slot, null);
}
}
It might take some work to factor this into your solution, but this might be an option.