What are the possibilities to avoid circular reference with Entity Framework 6 during JSON serialization with ASP.NET Web API?
I generated a edmx (Entity Data Model) file for Entity Framework 6, database first. I try to build an API with ASP.NET Web API. When I try to return my JSON object in my controllers I get a runtime exception of serialization because of circular reference.
Indeed when I double check my database and my entities I see one of my entity contains a list another entity that contain a list of my previous entity. let say I have a book entity that contains authors and each author entity contains a list of books. This is something common with relative database but impossible to resolve in JSON serialization (or impossible to resolve for the .NET serializer).
I don't want to change my database but I'm ready to break the wrong list into my entities or edmx file. What can I do?
What I have tried:
I already tried the solution that consist of creating new models or entities and using a mapping tool (http://www.codeproject.com/Articles/292970/Avoiding-Circular-Reference-for-Entity-in-JSON-Ser or the solution explained by by Shawn Wildermuth on Pluralsight).
This solution sounds more like a workaround than a real solution. It should exist something in edmx file or in Entity Framework to tell the JSON serializer what can cause circular reference, what can and must be serialized and what cannot be serialized, right?
There is technically no problem to serialize the domain model directly. To avoid circular reference you cannot use lazy loading. You must keep control of the loading. To do so
remove the virtual before each collection of your model (in code first approach)
set lazy loading configuration to false (in database first approach)
Don't try to serialize your domain model directly. Create a view model that returns the data in the exact format you want. Use you domain model to populate the view model. Much more information here Why do we use ViewModels?
You need to have a ViewModel that will act as the interface between your UI and your backend data structure.
Backend data structure is designed to be easilly stored and retrieved to and from the database. So by writing some ViewModel "adapters" you are not violating the "don't repeat yourself" rule.
Hope it helps.
I had to solve the same problem today. The easiest and the clear way for me was to remove the Navigation property from one of the entities on the entity model.
Open your model.edmx and remove the unwanted Navigation property which is causing the circular reference. In your case
Book references Author. so book entity model has Author navigation property.
If you do not want Author to reference Book, just remove Book navigation property from Author data model on the edmx file. So, there is only one way referencing.
Related
Let's say I have a set of classes that I want to share across multiple projects. For instance, I could use them in a REST service and also in a client that consumes that service.
So I create the following projects:
MyOrders.Models
MyOrders.RestApi
MyOrders.Client
Both the RestApi and Client projects have dependencies on the Models project.
The RestApi is using Entity Framework (code first) so normally you'd decorate the model's properties with things like [NotMapped] and [Key]. However, I don't want the Client solution to have any dependency on Entity Framework. None. So I can't decorate the models' properties with EF-specific attributes.
So my question is, is there some way to correctly set the models' EF-specific attributes from the RestApi project instead, maybe in the Context's constructor or something?
You can have the POCOs in your Models project, keep them totally ignorant of Entity Framework, and do the mappings in a separate project or in the RestApi project itself.
You can do this by the fluent mapping API, for instance in the OnModelCreating override of the context that you create in the EF-aware project:
modelBuilder.Entity<Order>().HasKey(o => o.OrderID);
modelBuilder.Entity<Order>().Ignore(o => o.OrderTotal);
etc.
This is a good argument for using custom Data Transfer Objects that are independent of the table-like entities. Although it can feel like overkill to have nearly duplicate classes - one as DTOs and one as EF Entities - there is another long-range benefit: the two sets of classes can vary independently. Let's say that you change the table table structure, but the client doesn't need to know about this change. Update the EF Entity but you leave the DTO alone, though you may have to update how you map from EF to DTO.
Speaking of mapping: EmitMapper can be a great help in transferring between the two types of objects.
You need to split your data access models from the rest of the application using Data Transfer Objects.
This will give a lot of benefits. At first it will look if your duplicating all the code of the model. But when your application grows, you will find that need the data in a view which is formatted in another way than how it was or is stored the database. Validation attributes can be added in a very specific way just the way you need it.
Mapping in between them can be done various ways. By hand or by using a tool like AutoMapper
This question already has an answer here:
ORM Entities vs. Domain Entities under Entity Framework 6.0
(1 answer)
Closed 7 years ago.
I start using Entity Framework about a year ago using Database-First approach. While reading and doing research online, I came across some terminologies that are confusing me. I was wondering if someone can help clear up some questions I have:
1) Using Database-First approach, I build my SQL Tables and create my edmx file from the database. From there, I start coding by create a Data Context and then accessing the entities. I recently read and see that I can right click in the .edmx file and "Add Code Generation Item" and then add "Ado.Net EntityObject Generator/EF 5.x DBContext Generator/EF4.x POCO Entity and etc. What is the purpose of these different code Generators? Am I suppose to implement them? When should I implement them?
2) I'm reading a lot about "object model and domain model". Is EF an object model or domain model ORM?
Thank you in advance for any information.
Add Code Generation Item
By default classes are generated with the help of EntityModelCodeGenerator. With the help of custom code generation, you can customize this. Why you would want to do ?
One example I could give from top of my head is - if you want to implement INotifyPropertyChanged interface by every single entity generated by EDMX. By default EntityModelCodeGenerator would not do that for you. Thus, you would want to customize this.
(Please note this is just my theoretical knowledge however the above example is quite a practical situation)
Domain Model vs Object Model.
Regardless the difference one thing for sure is Domain Model is Object Model too because in both cases you are defining classes, and association. This is how I define Domain Model and Object Model.
The only major difference could be how you are defining objects; in case of Domain Model, you are completely thinking from Business point of view and defining your objects.
From what I see that it is probably EF Database first is Object Model because when I am doing Database designing I am less thinking about Business, rather I am thinking about what is to be stored.
If am making POCO then I probably will be thinking from Domain Model point of view.
In case of EF - Code First, I have started thinking from Business point of view and make my association, then after I think of how objects will be stored.
So it is just a perception and at the end whether Domain Model or Object Model, ORM i.e. EF will provide you to persist this object into the database.
I hope it helps.
You don't normally need to use the "Code Generation Item" option. It is used to perform changes in the version of EF being used, and you could use it to do some custom code generation. In general, you should be able to leave this option alone.
EF is really an ORM (Obect-Relational Mapper). It takes objects and maps them to relations (tables). It can be used as either an object model or domain model (or both) as well depending on how you define those terms.
In C# is it possible to create a model of entities regardless of the database initially. Are there tools to create graphic entities in this way? What do you recommend?
Well, it's in your question as a tag - entity framework is a good tool for this. You can create classes, that you push later to the database.
Search for "code-first". Google will provide plenty of results I'm sure.
Edit based on the comment:
Well, in that case, try this: when you're creating edmx file, pick the second option - empty model.
From its description:
Creates an empty model as a starting point for visually designing a
conceptual model from the toolbox. Classes are generated from the
model when the project is compiled. You can specify a database
connection later to map the conceptual model to the storage model.
this may be the thing you want then.
I'm using Entity Framework 4.0 within a repository pattern to populate my POCO objects which are in another assembly. One of my objects contains an XML column from the database (a string type on the class).
Unfortunately, this XML string contains primary key IDs that I need to THEN use to retrieve other objects (with the repository) to build another custom object. I've been trying to do this using a custom get accessor on the domain object that tries to parse the XML and then go fetch from the repository. The problem is that this results in my model requiring the repository and gives me a circular dependency.
Is there any good way to do something like this? Perhaps some custom code to parse the XML column within the EF repository layer and map what I need to on a custom object in my model??
Any responses are greatly appreciated, thank you!
No there is no way to tell EF that XML column is actually other entity type. Once you move the logic to the get accessor you indeed break create model dependency on persistence which is something you are trying to remove by using POCOs. It will break your domain driven desing.
In domain driven design loading objects is strict responsibility of repository. So you need to build your retrieval method in the way that allows you to request loading related entities, for example:
load main object, parse XML and load relations in the same repository method
or load main object in single method and parse XML and load relations in another method
If the main object is not aggregate root for relations (they can exists separately) you should create separate repository for related objects and expose method just to load objects defined by XML string.
Is there a way to get entity objects to automatically pull all relevant data through the relationships instead of having having to .Include everything I want populated? I can't use lazy loading as this needs to be serialized to go over WCF. It would just be fantastic to have it auto populate the relevant collections.
No there is no build in feature which will automatically eagear load whole object graph. You must always explicitly say which navigation properties you want to eager load (by using Include method or LoadProperty method).
Edit:
Based on your comment: Generally it should be possible to build some auto loader - but it will not be easy. ObjectContext has MetadataWorkspace property which contains all metadata about your entities. You can load all information about your entities from metadata and add needed inclueds to the query. I expect one problem - you must somehow handle cyclic references. If you need some example how to extract information about entities check T4 POCO generation template.
I came across this querstion recently because I was looking for something similar.
Since EF Core 6 there is a AutoInclude method that configures whether a navigation should be included automatically.
This can be done in the OnModelCreation method in the DbContext class:
modelBuilder.Entity<Theme>().Navigation(e => e.ColorScheme).AutoInclude();
This would load the ColorScheme for every Theme when running the query:
var themes = context.Themes.ToList();
See Model configuration for auto-including navigations