[EDITED]
I am looking for a way to implement Linq To Entities in a WPF (MVVM) application and make each View (or ViewModel) responsible to manage their underlying entities separately.
Here is an example of a simple structure and what I would like to achieve:
[Customers] (1..1) <----> (0..* ) [Orders] (0..* ) <-- [OrderLine] --> (1..* ) [Product]
First view displays the list of customers
loads all the customers but not their orders
allows to Create or Delete customers
Second view displays the detail of a customer and the list of its orders
allows to Update the properties of the customer
loads all the orders of a specific customer, but not the orderLines
allows to Create or Delete orders
there might be several views managing separately several customers.
Third view displays the detail of an order and the list of order lines
allows to Update the properties of the order
loads all the orderLines of a specific order, and all products related to these orderLines
allows to Create or Delete orderLines
there might be several views managing separately several orders.
Fourth view displays the detail of a product
allows to Update the properties of the product
the related product might already be loaded by the third view
there might be several views opened at the same time and managing separately their own products. I do not want to update all the products at once but only the related product of the view.
According to Microsoft's recommendation, there must be one DbContext instance per view instance (or viewModel instance) (https://msdn.microsoft.com/en-us/data/jj729737.aspx).
The above scheme is of course very simplified. In the real application we will have much more entities and views. Aditionaly their might be different flows in which the views are opened, making it difficult to know in advance which entities are already loaded from the database when a new view is opened.
Still, there is one principle: a view (or the corresponding ViewModel) should be responsible to update the set of entities that it displays, without asking the DbContext to update entities handled by another view.
QUESTIONS
The DbContext of the productView should be able to push changes on the related product to the database. However, it should not load the product from the database if it was already loaded previously (i.e. by the DbContext associated to the orderLinesView). The problem is that a DbContext, as I understand it, encapsulates a transaction which makes me think it can hardly be responsible of saving entities that it didn't load by itself proviously. How to address such issue?
It is pretty clear that I must have a DbContext instance per view instance so that SaveChanges() only process the data of the current view. What is unclear is weather I should have several classes that inherits DbContext or a single class representing the DbContext of the application.
Is it necessary to add a DbSet<> property on the DbContext for each entitity type we want to update? That seems like the DbContext will need to change all the time as the application grows with new entities. Additionaly, that means repetitive code in the viewModels to point out which DbSet<> should be loaded, etc.
Wouldn't it be more efficient to have a mechanism (1) that can receive a set of entities to update (no matter their type), and another mechanism (2) that allows to select a set of entities to pass to mechanism (1)? The second mechanism could be either manual (for flexible scenarios) or automatic (by looking all the entities listed in a ViewModel for example).
If I want to put the database access mechanism in a web service, how can I continue to manage their underlying entities of each view separately ? In such case, where and how the DbContexts should be instantiated?
I look forward to any advices you can give.
You could be implementing something like the Unit of Work and Repository Pattern
This way you can keep the changes performed to the database as part of a work (window in your case) separated from the others. If you use the same context for all this is going to be complicated.
EDIT: trying to answer some of your questions:
1) As long as the next view doesn't alter the entities from other views you can pass the DTOs to it for logic on them. However this could cause some concurrency issues if the data you based your login on has changed. There is no easy way on working around this without saving all the entities related in one go. You can try to create your own cache and use it instead of querying the DbContext in those scenarios, but again this could be a problem with multiple users.
2 and 3) Have a look at the Unit of Work and Repository patterns I mentioned above. This should make a nice wrapper to avoid duplicating code.
4) For web service you should create a DbContext per each request, otherwise you could end up again with concurrency problems. Having a cache here could improve performance too.
Related
I am looking for solution(s) to providing a pick list in an application based on a domain model. I Have a Product model with a Product Repository. I have a UI which needs to display a pick list of Products. The pick list would only need to display 2 properties from a Product Model which has 15 properties.
I am thinking of creating a database view named ProductSummaries where each row in this view would be represented by a new Model called ProductSummary. This database view would be drawn from the Products table which is used for Product models.
Because this would be a database view, the creation of a repository for the ProductSummary model would only need one data access method which would be GetAll(). No modifications would be allowed on ProductSummaries because they are from a database view based on the Products table.
What other solutions are used to provide pick lists based on some properties of an existing domain model in an application? I don't know if what I am thinking of doing is something that will lead to problems.
Thanks in advance.
I don't know if what I am thinking of doing is something that will lead to problems.
What you've come very close to discovering on your own is cqrs -- the pattern of having one object to support queries that is separate from the object used to support mutations.
You should be fine, so long as you make it clear in your code that the Product Summaries are read only. (For example, if you use marker interfaces, then the summaries should be marked like values rather than like aggregates).
I'm using ASP.NET WebApi 2 and loading in part of a relational database structure into the front end website. This allows the user to make changes to multiple tables in a single store and to also view some extra data.
This mostly works pretty well. It means I can store changes to, say a person table and their related clothes and hair color on one call as follows:
db.person.Add(person);
db.SaveChanges();
The problem is that, I don't want to load all the related data. So where the shoe table may be loaded, I don't want the laces table to load with info about laces.
The issue I'm running into is that there is an attempt to store a duplicate shoe table to the database even though this was only loaded to allow the user to view these details. I imagine that this is because, I'm using [JsonIgnore] attributes to ignore certain parts of the object - it is thus recognizing this as a new object, when it isn't.
I could loop through the object removing any shoe information before call Add, but this would be slow.
Perhaps it is best to post a second object that only includes the items that have changed (after tracking these in the front end). Is there a better way?
When you use DbSet<T>.Add() in EF, the entity (or all the entitis in the tree, if it's an entity with related child entities) is attached to the DbContext as Added. That means that when you call SaveChanges EF will try to insert all the objects in the database. That's why you're getting duplication problems.
You need to learn how to work in disconnected mode with EF. Basically you need to track the state of each entity (i.e. control if they have to be inserted, deleted or updated), and set the correct state when you attach the entities in the context.
Look for docs on working with disconnected entities in EF, for example:
Persistence in Entity Framework
Add, Attach and Entity States
These will explain you how to handle disconnected entities.
This has probably already been asked and answered 1000 times, but Google has not been not my friend this morning.
I'm making the switch from using stored procedures and business objects to using Entity Framework. I like the simplicity of generating your POCOs from the generated EDM (Database-First approach here). And I like how much less typing it is.
I'm having a hard time wrapping my head around a suitable design for a VERY COMMON application scenario (in my world, anyway).
Basically, picture a data entry application, let's say for an online store's administrator (I'm doing it in WPF, but it could easily be web-based).
The admin will want to view a list of Customers (Manage Customers view) in a data grid. For each row, there is button to edit the Customer or delete it. At the bottom of the grid there is a button to create a new Customer.
If they delete a Customer, it is removed (after a confirmation) immediately from the data grid, as well as the back-end data store. If they edit a Customer, a window pops up (Edit Customer View), displaying the current data for that Customer. They can edit the data, then click either Submit, or Cancel. Submit saves the changes to the data store, and cancel discards the changes. Both buttons close the Window.
If, they click the New Customer button from the Manage Customer view, then a new Customer object is created (not saved to the DB yet), and the same Edit Customer view is opened, displaying the new, blank Customer.
Here is what I've got so far:
When the Manage Customers View Model is constructed, it populates a public list of Customers, something like:
public List<Customer> customers {get; set; }
using (WebStoreEndities context = new WebStoreEntities())
{
customers = context.Customers.ToList();
}
Then, if the admin user clicks the Edit button in a Customer row, the bound Customer object is passed to the constructor of the Edit Customer view. That view constructs its view model, which has the customer property that the view is bound to. The user can make their changes to the Customer object in the view, then either click Save or Cancel.
This is where I get lost. In my business object/stored procedure implementation, I would just have two Customer objects: one for the Customer being edited (bound to the view), and one copy of that Customer, called backupCustomer, used for reverting changes if they cancel out of the Edit Customer view (since I'm using MVVM, the properties of the Customer are changed immediately from the UI, and if they start making changes, and then click Cancel, they'll expect not to see their changes in that Customer).
More to the point, if they do click Submit in the Edit Customer view, that calls the Customer business object's Save() method, which reaches into the DAL and fires off the stored procedure to update the data store.
Okay, so now on to Entity Framework reality.
Issue #1. There is no way to save an individual entity. So even if I extend the Customer entity to have a Save() method, it would have to create a new WebStoreEntities context and call SaveChanges() on it:
using (WebStoreEntities context = new WebStoreEntities())
{
context.SaveChanges();
}
That seems weird to me. I wouldn't think you'd want have an entity instance creating entity contexts and stuff.
Issue #2. In my business objects implementation, I cache my objects, so I only need to ever fetch them from the DB once. If they make changes to a Customer, great. I just call save() on it and it updates the data store. Same with deletes and inserts. But I never have to fetch the same collection of Customers more than once (concurrency is not an issue on this particular project). In my EF implementation, every time they open the Manage Customers view, it's firing off the code above to get a list of Customers. I suppose I could just keep one data context open during the entire application, but that seems like a bad design too. Tying up a connection the the data store for the entire user session, just because they might open the same view more than once.
Please help me with my above issues, if you can, don't get hung up on what I'm about to say (it's just my initial impression anyway):
It seems like EF muddies the logical boundaries in my separation of concerns:
You have to keep a copy of the Entity connection string in your UI project (I keep my business objects and data objects in a separate project usually).
You can't tell an entity to save itself or delete itself. You have to do it from the underlying context, which is typically in the UI layer. In my UI, I like to be able to say myBusinessObject.Save() or myBusinessObject.Delete(), knowing that the object knows how to save or delete itself.
Anyway, it seems like EF is the future, so I'm going to stick with it. I would love your recommendations.
Thanks so much!
The Funk Monkey.
While most examples have you implement queries surrounded by a using you shouldn't actually do that in your case. Each EF context tracks it's own entity changes, by using multiple usings you won't know which context did the look up to call SaveChanges on it. So just use one context per user and dispose when your completely done (on exit, ect). You can use a singleton or a static class, in a desktop app it doesn't seem to make much difference from my experience. In an MVVM scenario you may be able to get away with the ViewModel handling the context as well, so when you instantiate your ViewModel instantiate your context and dispose your context on dispose, that might make more logical sense depending on how your handle the data internally.
For being able to revert changes EF actually tracks both the original DB version of the object as well as your changed version of the object. However to get that information is a little convoluted:
Disconnect and look up the entity:
((IObjectContextAdapter)myContext).ObjectContext.Detach(dbObject);
var entry = myContext.Entry(dbObject);
var original = entry.OriginalValues;
Personally I just handle copying and keeping the original object in code, it's cleaner and seems to be safer. It's also probably faster, but I've never run tests to prove that. If you're in a multi-user environment you may benefit from simply reloading the data from the DB though so that you don't mistakenly display stale data.
Issue #1: You want you entity to have a Save method but you want to avoid creating a coupling between the entity and the persistence layer (e.g. the EF context)? Well, if the Save method is implemented by the entity then you cannot avoid that. Better perhaps, is to move the Save method to a repository:
repository.Update(entity);
Now it is the responsibility of the repository to create the EF context, not the entity.
Issue #2: EF contexts are lightweight and the normal pattern of usage is as you describe where the context is created transiently and then disposed after changes have been saved. Conceivably, you can create a desktop app the has one context for the lifetime of the application but if the database is changed while the app is running the content of the context will get out of date. Sooner or later inconsistency in state will hit you and I would think that you get a more maintainable application if you stick to the transient context pattern. If you are writing a web app you will not have the option to keep a database context alive between requests and that pattern has proven to be very successful when writing business apps.
So I recommend this:
Implement persistence in a repository or service class, not in the entity class.
When reading or writing entities do it in a manner that ensures that the EF context only exists for the duration of the operation (unit of work). Optionally, you can use a row version number to ensure that an entity cannot be updated if it has been changed in the database after the last write.
By the sounds of it...you prefer the ActiveRecord pattern...but EF follows the UnitOfWork pattern...in your case you are using POCO Entities....which are "persistent-ignorant".
http://randolphcabral.wordpress.com/2008/04/03/active-record-vs-unit-of-work/
refactoring: swicthing from custom data access layer to Entity Framework
One approach to hide the "EF technology", is to create a "repository" layer inside of which you hide all the EF logic i.e. management of the "context". But creating another layer can be a lot of repetitive work. Typically your repositories would share the same context.
http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx
http://www.dataworks.ie/blog/entity_framework_5_with_automapper_and_repository_pattern
If you keep the EF context around, then it manages the change-tracking and caching of already retrieved objects for you.
Alternatively, you can work in a disconnected mode...where you create the context each time you want to retrieve/perist entities...however, you then have to do the caching and state-tracking yourself and "reattach" the objects to the context, before submitting.
I have a setup with Client -> WCF -> POCO -> EF4.
Say I have a list with A entities. The A entity contain among other properties a huge list of B entities that isn't loaded by default. When a certain action is done on the client, it may need to know the list of B entities...
If I load the B entities for the A entity and attach them to the collection, the A entity is in effect changed, and I guess when saving the entity it will also save these 'new' B entities to the A entity?
I could wire up a GetEntityWithAllDetails function, but then I would get some data that I already have, and if there were other collections I didn't want to load, it would be a complete mess.
The question can be boiled down to how can I recomplete the POCO on the client side when I only have a partial POCO to start with and want to avoid loading data twice and still being able to rely on EF4 to save the entity correctly?
That is a complex task and EF doesn't handle it - it is your responsibility. When you use detached entities the change tracking is up to you.
Your solution currently probably is:
Client sends request to WCF service
WCF uses EF to get data, close context and return POCO graph or partial graph back to client
Client modifies the POCO graph / partial graph and sends modified data back to WCF service
WCF creates new EF context and saves the POCO graph
Sounds easy but it doesn't. In the last step you must manually explain to the new context what has changed. It generally means heavy interaction with ObjectStateManager (in case of ObjectContext API) or DbChangeTracker (in case of DbContext API). It also means that you must pass information about changes from the client.
For example suppose that you are modifing Order entity. Order entity is dependent on Customer entity and it has dependent OrderItem entities. To make this interesting suppose that OrderItems must be processed by different warehouses so each warehouse has access only items assigned to it.
In the step one you will request Order from one warehouse
In the step two you will retireve Order without Customer and with a supset of OrderItems.
In the step three the warehouse modifies sevaral OrderItems as processed. Deletes single OrderItem because of discontinued product and inserts another OrderItem for replacement of discontinued product. Because of insufficient supplies some items will be unchanged. The warehouse sends Order back to the server.
What will you do in the step four? You must apply some knowledge. The first knowledge is that cutomer was not send to client so you can't modify a customer relation. In case of foreign key relation it means that CustomerId can't be modified. Now you must explicitly say which OrderItem was updated (= exists in DB), which was unchanged (= doesn't need any action), which was inserted (= must be inserted) and the worst part which was deleted (if you don't send some information about deletion from the client you can't know it without reloding the entity graph from the database).
At least you can be happy that EF will not delete anything you explicitly don't mark for deletion. So order items related to other warehouses and their relations to the order will be unchanged.
There are two general approaches how to deal with it:
Load entity graph first and merge changes into the graph. Then save the attached (loaded) graph. You will simply compare the loaded entity graph with the received entity graph and process all required updates, deletes, inserts.
Use self tracking entities instead of POCOs which are implementations of Change set pattern and are able to track changes on the client. STEs have some disadvantages which make them useless in certain scenarios.
There is also completely separate architecture approach using DTOs instead of direct EF POCOs but it results in same complications as you have at the moment.
Welcome to n-tier development.
This sort of situation is exactly why many architected enterprise scale solutions use data transfer objects between tiers.
I would recommend avoiding domain entity propagation from the service (business) tier to the client. If you go down the track of having entities become aware of whether they are fully loaded, or what tier they are currently on, they are hardly "POCO" are they?
So you write a service method "GetEntityWithAllDetails". It should take a GetEntityWithAllDetailsRequest object and return a GetEntityWithAllDetailsResponse object containing whatever the caller of the service expects, and no more.
Obviously there is a far bit of mapping to be done between between DTO's and domain objects - libraries such as Automapper (and others) can help with that.
Propagating domain entities to the client also retricts your flexibiltiy with regards to lazy or eager loading of entities and leaves you having to deal with re-attaching/merging entities, which is problem with EF becuase it will not re-attach entity graphs - you must walk the graph manually.
I will try and say it really plainly. Propagating domain entities from the service to the client is the road to programming hell and very quickly leads to objects having all sorts of responsibilties that are orthoganol to their purpose.
Whenever I read an article on linq to entities, I sounds like I should embed my business logic in the generated entity-classes.
This would means that the "user" of the business-objects (controller, service-layer, ...) would have to know about the datacontext-object that's needed to use linq.
It would also mean that the DAL-logic and the business-logic will be mixed up.
A lot of microsoft examples use some kind of DTO-approach. I'm not a big fan of the DTO pattern.
So should I let the business-object encapsulate the linq-entity and provide access to it using properties, or should I stick with the DTO pattern?
What are your suggestions?
Thanks
The entity model generates partial classes. In a project of mine I'm using an entity model inside a class library and added a few .cs files to it that add functionality to the default entity classes. (Mostly functions related to error and message logging to a database table and a method to import/export all data to XML.)
But true business logic is located in a second class library that refers to this entity class library.
Let's explain. First I created an entity model from a database. It contains a list of company names and addresses. I do this by choosing "New project|Class library" and then add an ADO.NET Entity Data Model to this library. The Entity model will be linked to my SQL Server database, importing the tables I need and auto-creates classes for the tables I want to access.
I then add a second .cs file for every table that I want to expand. This would be a few raw methods that are strongly linked to the database. (Mostly import/export methods and error logging.) This I will call Entity.Model, which will compile to Entity.Model.dll.
Then I add a second project which will contain the business logic. Again, I use "New project|Class library" to create it and add Entity.Model.dll to it's references. I then start writing classes which will translate the database-specific classes to more logical classes. In general, I would not have to make many changes except that I will protect or hide certain fields and add a few calculated fields. The business logic would only expose the functionality that I want to access from my client application and not a single method more. Thus, if I don't allow the client to delete companies then the "Delete" function in the entity model will not be exposed in the business layer. And maybe I want to send a notification when a company changes their address, so I'll add an event that gets triggered when the address field of the company is changed. (Which will write a message log or whatever.) I'll call this business.logic and it compiles to Business.Logic.dll.
Finally, I'll create the client application and will add a reference to Business.Logic.dll. (But NOT to the entity model.) I can now start to write my application and access the database through the business layer. The business layer will do validations, trigger a few events and do whatever else in addition to modifying the database through the entity model. And the entity model just serves to keep the database relations simple, allowing me to "walk through" the data through all foreign links in the database.
I wouldn't edit the generated files as they are likely to change.
What you could do is wrap them some query object and pass that around.
ayende makes a very good point about where the DAL should really live
Also, you should be a fan of viewmodels/dtos ;)
I prefer to wrap calls to the entity classes in business classes. (Call it BC for short.) Each BC has several constructors, one or more of which allows the context to be passed to it. This allows one BC to call another BC and load related data in the same context. This also makes working with collections of BCs that need a shared context simpler.
In the constructors that don't take a context, I create a new context in the constructor itself. I make the context available through a read-only property that other BCs can access.
I write using the MVVM pattern. The nice thing about this approach is that so far I have been able to write my viewmodels without ever refering to the data context, just the BCs that form my models. Hence if I need to modify my data access (replace entity framework, or upgrade to version 4 when it is out of beta) my views and viewmodels are isolated from the changes required in the BCs.
Not sure this is the best approach, but so far I have liked the results. It does take tweaking to get the BCs designed correctly, but I end up with a flexible, extensible, and maintainable set of classes.