Handling Multiple entities with a Custom Cache mechanism - entity-framework

We built a mechanism that on server request automatically retrieves the entities list from the DB, and maps them to ViewModels. We can't figure out how to support clearing View Models that are built from multiple DB entities when an update was made to some relevant DB entity.
This is how we've built our Cache:
We have a mapping between the key (the DB entity name) and the list of values it holds (View models).
This is how we handle entities invalidate:
On EF's Context Save method, we clear the Cache values by the saved entity's name (when it has been changed).
For most entities, all the Cache values are mapped to a single entity.
For some entities however, the Cache values depend on several other entities (which are either direct or indirect navigation properties of the entity).
For instance:
We have an EducationPlace Entity.
Its Cache key is "EducationPlace". Its values are a list of EducationPlaceViewModel.
EducationPlace entity has an Address property, and the Address entity, has a City property.
City's name is used in the EducationPlaceViewModel.
Now we want, that when the City entity is being updated, the Cache's EducationPlaceViewModel list will be cleared.
What we are looking for, is a way to update a cache entry, when an entity that the cache entry's View Model depends on is being updated.
The two solutions we've considered are:
Use reflection to find which entries should be cleared (by following the navigation properties). This will create many unnecessary dependencies, which will result in many redundant cache clears. For instance, EducationPlace has many navigation properties that are not being used by its View Model, hence should not trigger a Cache clear.
Use a custom Attribute that will decorate each relevant entity, and will hold its list of entities that its View Model depends on. This way we will easily get the entities that should be cleared when an entity is being saved at the Save method.
This way requires A LOT of maintenance. It requires for each new entity which its View Model depends on other entities for the developer to remember to use it on the new entity, and to update that entity when its View Model depends on new entities.
This is how we clear the View Models.
This method is invoked from the Context's Save method:
What this method basically does is:
It gets all the DB entities from the DAL layer
For each entity name, it:
a. Skips none-relevant entities
b. if the entity name exists as a Cache key - Clear its data

Related

Do I have to set foreign key properties manually when I change associations?

I'm migrating from Linq-to-SQL to Entity Framework (4.4), using Database First with a DbContext. I'm wondering whether the following behavior is normal:
using (var e = new AgendaEntities()) {
var store = e.Stores.First();
var office = e.Offices.Create();
office.Store = store; // Set association
Console.WriteLine(office.StoreID); // shows Guid.Empty, expected store.ID!
}
In L2S, setting the Store association to an entity would also update the StoreID key. In EF, this doesn't seem to be happening. This is regardless of whether the entities are new or loaded from the context.
When I SaveChanges, it saves correctly and the StoreID is updated to match office.ID, but why does this only happen after the save?
Is there something I'm missing, or am I now supposed to keep foreign keys in sync manually?
Solution Edit:
This is called property fixup, and used to be done automatically by the generated proxies. However, with DbContext this is no longer the case. According to this Connect issue, this is by design.
Hello,
The DbContext template actually doesn't generate classes that will be used as change tracking proxies - just lazy loading proxies (which don't do fix-up). We made this decision because change tracking proxies are complex and have a lot of nuances that can be very confusing to developers.
If you want fix-up to occur before SaveChanges you can call myContext.ChangeTracker.DetectChanges.
~EF Team
An alternative is to call DbContext.Entry(entity), which will sync up the entity. This is described in this article: Relationships and Navigation Properties under "Synchronizing the changes between the FKs and Navigation properties"
No. Entity framework does this for you. Read Relationships and Navigation Properties for more information.
By assigning a new object to a navigation property. The following
code creates a relationship between a course and a department.
If the objects are attached to the context, the course is also
added to the department.Courses collection, and the
corresponding foreign key property on the course object is set to the
key property value of the department.
course.Department = department;
But as you observed, this only happens after you call SaveChanges or one of the other actions mentioned in the "Synchronizing the changes between the FKs and Navigation properties" portion of the document linked above.
If you are using POCO entities without proxies, you must make sure
that the DetectChanges method is called to synchronize the related
objects in the context. Note, that the following APIs automatically
trigger a DetectChanges call.
DbSet.Add
DbSet.Find
DbSet.Remove
DbSet.Local
DbContext.SaveChanges
DbSet.Attach
DbContext.GetValidationErrors
DbContext.Entry
DbChangeTracker.Entries
Executing a LINQ query against a DbSet
If this is not happening at all, my guess is that you haven't properly defined StoreID as the foreign key of the navigation property Store.

Can I use Entity Framework objects outside database scope?

I am designing a database for storing products and some properties belonging to them. The properties can be inherited from parent product to the child product. For example:
ProductA ---> PropertyA, PropertyB
|-ProductB ---> PropertyC
In this example, ProductB should have PropertyA and PropertyB in addition to PropertyC. In order to get all the properties of a certain product, I need to go through all the parents and accumulate all the properties in a list. However, the Property class itself is a database entity, so can I use it to define normal objects (i.e. detached from database) without having them affecting the database contents, i.e. create, modify, delete instance as normal C# objects?
Yes you can. Entity Framework 4.0 onwards supports what is known as a POCO entity (Plain Old CLR Object). They can exist entirely separately from your database concerns and when appropriate you can attach them to an instance of an Entity Framework Context for persistence to the database.
Likewise you can Detach entities from a Context having retrieved them from the database through the same Context should you choose to manipulate them within your Domain Model in such a way that you don't want them persisted again.
Depending on whether you're doing true Code First or Database First will determine the development workflow you use for creating these entities.

Entity Framework Service Layer Update POCO

I am using the Service Layer --> Repository --> Entity Framework (Code-First) w/POCO objects approach, and I am having a hard time with updating entities.
I am using AutoMapper to map my Domain Objects to my View Models and that works good for getting the data, no how do I get that changes back into the database?
Using pure POCO objects, I would assume that there is no sort of change tracking, so I see my only option is to handle it myself. Do you just make sure that your View Models have the EXACT same properties as your Domain Objects? What if I just change a field or two on the View Model? Won't the rest of the fields on the Domain Object get overwritten in the database with default values?
With that said, what is the best approach?
Thanks!
Edit
So what I am stumbling on is this, lets take for example a simple Customer:
1) The Controller has a service, CustomerService, that calls the services GetCustmoerByID method.
2) The Service calls into the CustomerRepository and retrieves the Customer object.
3) Controller uses AutoMapper to map the Customer to the ViewModel.
4) Controller hands the model to the View. Everything is great!
Now in the view you do some modifications of the customer and post it back to the controller to persist the changes to the database.
I would assume at this point the object is detached. So should the model have the EXACT same properties as the Customer object? And do you have to make hidden fields for each item that you do not want to show, so they can persist back?
How do you handle saving the object back to the database? What happens if your view/model only deals with a couple of the fields on the object?
If you're using EF Code First, i.e: the DbContext API, then you still do have change tracking which is taken care of by your context class.
after making changes to your objects, all you have to do is call SaveChanges() on your context and that will persist the changes to your database.
EDIT:
Since you are creating a "copy" of the entity using AutoMapper, then it's no longer attached to your context.
I guess what you could do is something similar to what you would in ASP.NET MVC (with UpdateModel). You can get the original entity from your context, take your ViewModel (which may contain changed properties) and update the old entity, either manually (just modified properties), or using AutoMapper. And then persist the changes using context.SaveChanges().
Another solution would be to send the model entity as [part of] the ViewModel. This way, you'll have your entity attached to the container and change tracking will still work.
Hope this helps :)
You are absolutely right that with a detached object you are responsible for informing the context about changes in your detached entity.
The basic approach is just set the entity as modified. This works for scalar and complex properties but it doesn't work for navigation properties (except FK relations) - for further reading about problems with navigation properties check this answer (it is related to EFv4 and ObjectContext API but same problems are with DbContext API). The disadvantage of this approach is that all fields in DB will be modified. If you just want to modify single field you still have to correctly fill others or your database record will be corrupted.
There is a way to explicitly define which fields have changed. You will set the modified state per property instead of whole entity. It is little bit harder to solve this on generic approach but I tried to show some way for EFv4 and for EFv4.1.
I agree with #AbdouMoumen that it's much simpler to use the model entities at the view level. The service layer should provide an API to persist those entities in the data store (db). The service layer shouldn't dumbly duplicate the repository lawyer (ie: Save(entity) for every entity) but rather provide a high level save for an aggregate of entities. For instance, you could have a Save(order) in the service layer which results in updating more basic entities like inventory, customer, account.

How to store information edited or created in more than 1 entities

In my ASP.net MVC application, i want to store the information, that was edited or created, in several different entities (persons, address, ..).
So my create view exist of input fields for each attributes in persons table and address table. Now I want to store the values in both entities at the same time?
Is this the same approach as with retrieving using a ViewModel? Or is there a better approach ?
You could indeed make your view typed to a view model that encapsulates all the entties you need for that view, but when it's time to store them in the database you'll still have to do it every entity individually, so for example you have:
// here you got hold of your entities already;
// we are in your action method
// this is your context, but please use
// Dependency Injection in your controller ^_^
var context = new dbContext();
context.Add(person);
context.Add(address);
// This will store all the entities you've added in one go.
context.SaveChanges();
SaveChanges() works as well when you neet do update entities, as long as you retrieve said entities through the same context.

RIA services presentation model with 1-many or many-many relationships

I'm trying to get a presentation model (discussed here and here) working in RIA. All the examples I can find are simple, flat data entities with no 1-many or many-many relationships, which are what I can't get working - specifically, on updates and inserts into associative relationships.
Queries I can get working fine - I have my presentation classes marked up with Association attributes (and Include attributes, where appropriate), and I have a good understanding about how data is loaded into the client side and maintained there as entities. I also have inserts of new entities covered. However, I'm experiencing the following problems. For the following examples, assume we have simple Album and Artist entities, where an Album has a single artist and an Artist can have zero to many albums. Both have a Name property.
On the client side, if I do myArtist.Albums.Add(anAlbum) or myArtist.Albums.Remove(anAlbum), nothing happens. HasChanges returns false. (Note that myArtist and anAlbum were obtained solely in code by loading the entities and iterating to get references to specific entities: I'm not doing anything in UI or with DomainDataSources yet, just dinking around).
If I update the Name on an Artist and SubmitChanges, when the Update method gets called on the server, the Albums collection is null.
Does anyone have any suggestions, or can you point me to an example that uses more complex objects?
EDIT (keeping the above for posterity): Alright, it appears that the second issue (a reference to an entity or a collection of entities showing as null when Update gets called on the server) exists because the child entites aren't marked as Changed and so they aren't being serialized and sent back. I know you can force that to happen by using [Composition] and I have gotten it to work that way, but this is not a compositional relationship and I want both entities to be "top-level" entities. How can I mark an entity as changed?
The problem was that my [Association] attributes weren't correctly defined. I didn't realize that the association's Name property has to be the same on both sides of the association. When the names are the same and you do a build, the generated code on the client uses a different constructor for the EntityCollection used by the "parent" to refer to the "children" than it does if the associations aren't set up right. The new constructor takes callbacks that do a little bit of extra handling when you call Add and Remove on the collection - specifically, they take the child entity you are adding or removing and modify the property on it that refers to its parent so that everything remains in sync: the collection you removed the object from, the collection you added it to, and the object's reference to its parent.