WPF and LINQ/SQL - how and where to keep track of changes?
I have a WPF application built using the MVVM pattern:
- My Models come from LINQ to SQL.
- I use the Repository Pattern to abstract away the DataContext.
- My ViewModels have a reference to a Model.
- Setting a property on the ViewModel causes that value to be written through to the Model.
As you can see, my data is stored in my Model, and changes are therefore tracked by my DataContext.
However, in this question I read:
The guidelines from the MSDN documentation on the DataContext class are what I would recommend following:
In general, a DataContext instance is designed to last for one "unit of work" however your application defines that term. A DataContext is lightweight and is not expensive to create. A typical LINQ to SQL application creates DataContext instances at method scope or as a member of short-lived classes that represent a logical set of related database operations.
How do you track your changes? In your DataContext? In your 开发者_如何学GoViewModel? Elsewhere?
When I write this kind of software, my VMs never have a reference in any way to the data model. When you couple them like this, you are pretty much married to a simple two-tier solution which can be really tough to break out.
If you disconnect the DataContext entirely from your VM and have them live on their own, your application becomes:
- Much more testable -- your VMs can be tested without the datacontext
- Potentially stateless at the data layer -- it's easy to change your architecture to adopt a stateless 3-tier based solution.
- Able to easily integrate other data sources -- your VMs can elegantly contain aggregates and combinations of other data sources on their own.
So in short, yes, I would recommend decoupling the data access classes from the ViewModel objects throughout the app. It might be a bit more code, but it will pay dividends down the road with the architecture's flexibility.
EDIT: I don't use the change tracking features of the L2SQL objects once they've crossed a distribution boundary. That turns into a can of worms pretty quickly -- you can spend a lot of time with the care and feeding of your data model's object graph inside your viewmodel - which adds not only complexity to the ViewModel, but at least transitively couples the ViewModel to the schema of the database. Instead of doing that, I make the ViewModel pure. When the time comes for them to be persisted, your service layer/repository/whatever does the translation between the ViewModel and the data objects. This at first seems like a lot of work, but for anything other than simple CRUD, this design pays off pretty quickly.
However you manage data inside a program, instances of objects of L2SQL generated classes are created like regular objects, without any using of a data context. DataContext is only responsible for interacting with a database.
Those guidelines may mean that you can do anything with objects of L2SQL generated classes, but don’t keep an object that transfers data between them and a database. You can treat L2SQL classes like any other classes, which you can use as you want, with an additional capability of being read from and written to a database.
This is a guess. I cannot say what was in the head of the MSDN author of that magic phrase, but this explanation makes sense. Store data in L2SQL generated classes objects during the whole program’s activity and synchronize it with database by temporary DataContext objects.
精彩评论