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.
Related
I am implementing DDD with Entity Framework Code First. My Domain Model is persisted as it is without any mapping layer.
I am following approach suggested during Tech-Ed by Julie Lerman. Each bounded context maps to different schema within same database.
If same entity say, Customer appears across different bounded contexts
how do we maintain consistency of data for Customer entity?
Only a single bounded context will be the system of record for your entity. If you cannot get away with simply an Id in the other BCs then you can include a subset of the entity (usually not all the properties) as a value object.
Any changes to the entity in the SOR should be published as one or more events in a messaging system that the downstream BCs subscribe to in order to keep their data eventually consistent.
In Julie Lerman's example with Entity Framework (EF) she models a Contact under two different bounded contexts - Sales Order (being read only) and Contact Management (being persistable)). As Eben suggests keeping these entities eventually consistent can be achieved using a messaging system - in Julie's example she uses the ContactUpdatedEvent domain event which can be subscribed to by a service to enforce a model within a different bounded context to be reread from a data source (whether this is a database or the event itself contains the data in a DTO for example) when this event is published - this will help ensure eventual consistency of data.
Because your controller/view model/presenter/services should be interacting directly with an abstracted interface for persisting changes, i.e. the repository pattern rather than the EF db context directly, then in the example above one Contact will come from one repository under one root aggregate and the other Contact will come under another root aggregate - therefore the two Contact entity implementations will support persistence of the root aggregates in different ways, in which the Sales Order context will prevent the persistency of the Contact entity.
As you will represent the Contact under two different bounded contexts they shouldn't share the same behaviour so you shouldn't really worry about any code duplication apart from the naming of properties for getting/setting data, but I'm sure this is something you can live with. For example, an action of "Asking a contact to review their order" COULD be represented with behaviour on the Contact class under the Contact Management context, but MAY have no relevance in the Contact class on the Sales Order context.
The EF doesn't force you to have associations between entities in both directions. The Fluent API mapping provides a lot of flexibility and can allow you to have these associations one way.
If the idea of your project is to follow DDD then I'd suggest you forget about the database and EF completely to start with and use in-memory repositories for reading and persisting your root aggregates. You can then focus on mapping your domain entities to your database using the EF Fluent API at a later date and this way you won't be forced to change your domain model to "fit" your database.
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.
[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.
I am using ADO.NET, I have created DAL and BAL, structure is as follows
DAL
-POCO(Table to Entities mapping)
-Repository (Add, Delete, Edit, Select, Search)
BAL
-POCO(DAL to Entities mapping where Entities are complex type here)
-BusinessManager(Validation and Business rules)
I will be exposing BAL using services. And multiple applications like Web, Window, Mobile will be consuming this BAL.
I am not sure where should Sql Transactions be started. Who is responsible for creating a complex entities.
e.g. Complex entity could be
Entity
-Entity Type
-Contacts
-EmployeesReporting
-ReportingTo
Now who should create an Entity? Is it a BAL or DAL. Where should SqlTransactions be started? How should I make these entities to support lazy loading as I am a supporter of Stored procedure and prefers to use one database connection per request
I'm not sure I see how your desire to use one database connection per request fits with your desire to support lazy loading.
The point of lazy loading is that you don't need to materialize certain parts of the object graph when initially loading it, and you may or may not need to load those parts at some later point in program execution.
Reserving a connection somehow to satisfy that need would be very wasteful of a precious resource (DB connections).
Since the object graph is being used in the Business Access Layer, parts of the object graph that were not initially materialized must somehow be represented in a manner that allows you to intercept requests to have them available, and produce them on demand. The EF solution of placing a proxy in the business layer that, in turn, activates the DAL to fetch missing parts of the object graph on demand, is a good one.
I've been reading about self-tracking entities in .net and how they can be generated from a *.edmx file. The thing that I'm struggling to understand is what generating these entities gives you over the basic EF entities? Also, some people have mentioned self tracking entities and Silverlight, but why would you use these rather than the client side or shared classes generated by RIA services?
What is the point of self-tracking entities and why would you use them?
Self tracking entities (STE) are implementation of change set (previous .NET implementation of change set is DataSet). The difference between STE and other entity types (POCO, EntityObject) is that common entity types can track changes only when connected to living ObjectContext. Once common entity is detached it loose any change tracking ability. This is exactly what STE solves. STE is able to track changes even if you detach it from ObjectContext.
The common usage of STE is in disconnected scenarios like .NET to .NET communication over web services. First request to web service will create and return STE (entity is detached when serialized and ObjectContext lives only to serve single call). Client will make changes in STE and pass it back in another web service call. Service will be able to process changes because it will have STE internal change tracking available.
Handling this scenario without change tracking is possible but it is much more complex especially when you work with whole object graph instead of single entity - you must manually merge changes received from client to current state in database.
Be aware that STEs are not for interoperable solutions because their functionality is based on sharing STE code between server and client.
The main purpose is to aid in N-tier development. Since they're self-tracking, you can serialize them over, say, a WCF service, then de-serialize them back, and they will still know which changes have been made, and are pending for the database.
Self-tracking entities know how to do
their own change tracking regardless
of which tier those changes are made
on. As an architecture, self-tracking
entities falls between DTOs and
DataSets and includes some of the
benefits of each.
http://blogs.msdn.com/b/efdesign/archive/2009/03/24/self-tracking-entities-in-the-entity-framework.aspx