ef4 cause Circular reference in web service - c#

I have a Reason object:
public class Reason
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual Company Company {get;set;}
}
I am using entity framework 4 and Company is navigation property to Company.
I also use webservices in order to return data to the client.
I have web method that returns Reasons:
[WebMethod]
public Reason[] GetCallReasons()
{
IReasonRepository rep =
ObjectFactory.GetInstance<IReasonRepository>();
return rep.GetReasonsList().ToArray();
}
Because of the ef4 I get the following exception for executing the web method:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Reason_24A0E4BBE02EE6BC2CF30BB56CFCB670C7D9D96D03D40AF4D174B89C9D3C5537'
The problem accurs because ef4 adds property that can't be serialized:
In order to solve this and eliminate the error, I can disable the navigation property by not making it virtual or by remove the navigation property. But I neet it and want to use the lazy loading feature.
I also can write spesific serializer for Reason but I have many many classes the I used in my web-services and write a serializer for all of them is a lot of work.
How can I solve this exception?..

There are multiple solutions for your problem and they really depend on the type of service you are using and on the type of serialization:
The clean approach is using DTO (data transfer objects) as #Mikael already suggested. DTO is special object which transfers exactly what you need and nothing more. You can simply create DTOs to not contain circular references and use AutoMapper to map between entities and DTOs and vice versa. +1 for #Mikael because he was the first to mentioned this.
All other approaches are based on tweeking serialization as #Haz suggested:
WCF and DataContractSerializer: explicitly mark your entities with DataContract[IsReference=true] and all properties with [DataMember] attributes. This will allow you to use circular references. If you are using T4 template to generate entities you must modify it to add these attributes for you.
WCF and DataContractSerializer: implicit serialization. Mark one of related navigation properties with [IgnoreDataMember] attribute so that property is not serialized.
XmlSerializer: mark one fo related navigation properties with [XmlIgnore] attribute
Other serializations: mark one of related navigation properties with [NonSerialized] (+1 for Haz he was the first to mention this) for common serialization or [ScriptIgnore] for some JSON related serialization.

I usually write specific classes for the webservice. While this is some extra work it has the advantage that the webservice gets more robust as small changes in your entities won't go unoticed and silently fail on the side of the consumer/javascript. For example if I change the name of a property.
There are a few things you can do to reduce the work and one is to use AutoMapper which can automatically map between objects.

You haven't supplied the definition for your company class.... But I'm guessing you have a collection of Reason as a property.
Lazy loading in an SOA Enviroment doesn't really work. You can't have unlimited lazy navigation over a serialized class, once you leave the webmethod you have no way to call back into the original datacontext from the webmethod consumer to lookup the properites... so the serializer will try and visit all properties, including lazy properties at the time of serialization.
You need to disable serialization on one part of the circular reference, either on the Reason collection in Company class, or the Company in Reason class.
You can use the "NotSerialized" attribute to disable serialization of a particular field.

Related

How to serialize entity if using lazy loading in entity framework?

I just started to learn entity framework and i am facing the problem related to serialization of generated Models. I have tables with one to many relation which are Country and State as one country have many states. I am using the DB first approach and when i create the entities using Entity Framework, the class Country has one property of ICollection. I read and found that this is the navigation property. Let me show the generated class first which is below:
//This is the generated class.
public class Country
{
public Country()
{
States = new HashSet<States>();
}
public int Id { get; set; }
public string ContryCode { get; set; }
public string ContryName { get; set; }
public virtual ICollection<States> States{ get; set; }
}
I generated Models and then i step forwarded. Then i got the problem of serialization when i request via ajax to get the list for Country. I googled and found some terms like lazy loading, eager loading and n+1 problem. I read about it in detail. I found a solution which was turning off the lazy loading. Now the question is How i can serialize my Model with lazy loading?
I have created MetaData class and use some attribute like ignoreXml etc but nothing helped. By the way i am using Asp.Net MVC 5 and i want to serialize my Model with lazy loading. Can any one explain?
When you use lazy loading, execution is deferred until the value of the property is actually needed. You are probably encountering an error because the context has been disposed by the time the property is accessed. Consider the following scenario:
You have an object called Country with a lazy-loaded property called States.
You get this object from a context.
The context is disposed.
You call the States property.
The property goes looking for the context it came from.
An error is thrown because "the context has been disposed".
Code Sample:
using(var context = new SomeEntityContext())
{
var country = context.Countries.First();
}
//This will throw an error because the context was disposed of.
var states = country.States;
The serializer would also throw an error because it will go through the properties of the object, it will find States and it will try to get its value.
Even if the context is still alive, you could run into a loop with navigational properties during serialization. this is because both objects hold a reference to each other. Consider the following scenario:
You have an object called Country with a lazy-loaded property called States.
The serializer attempts to serializer the object of type Country.
It reads the States collection.
It attempts to serialize every object of type State.
It reads a property of type Country.
It attempts to serialize the object of type Country.
It reads the States collection.
It attempts to serialize every object of type State.
It reads a property of type Country.
It reads the States collection.
It attempts to serialize every object of type State.
It reads a property of type Country.
It reads the States collection.
It attempts to serialize every object of type State.
It reads a property of type Country.
.... (endless loop, well, at least until you run out of stack frames).
Alternatively, you can create a custom serializer that will avoid the pitfalls of navigational properties, but that is probably more work than it's worth. This approach is best suited for situations where the serialized version differs significantly from the object.
This is why you are better off using a Data Transfer Object (DTO). Map the data to this object and send that over the wire. There are components out there that can do the mapping for you, if you keep the structures as similar as possible.
Check out AutoMapper: http://automapper.org/

Mapping Properties of type of Complex Type to DB Columns in EF 6 using code first and custom EntityTypeConfiguration implementation

This is my first activity with great stack overflow, but absolutely not my first time to visit the website.
My Question:
In our project, we are extending the EntityTypeConfiguration to take control over the mapping of entities to the DB in code first fluent API.
What I am confused with is how it is possible to include the configuration of complex types in the ctor of derived configuration, i.e. The configuration of primitive properties is possible through "Property" method of base EntityTypeConfiguration, but when calling this method on properties of type of Complex Types, the project builds will stop at called method.
Actually, the DB will be generated by entity table containing multiple columns, representing the fields of the embedded Complex Type using "PROPERTYNAME_INNERFIELDNAME" naming convention, even though if the complex type be of class type.
So, I do not know how to overcome with the issue if the complex type be of class type.
Thank you for your kind consideration.
My Code:
class Entity
{
long Id;
Address Addr;
}
class Address
{
string City;
string ZipCode;
}
class EntityConfig : EntityTypeConfiguration<Entity>
{
EntityConfig()
{
Property(p=>p.Addr); //Build error
}
}
Firstly, thanks to dear Bardware.
My problem has been solved by using following configuration:
Property(p=>p.Addr.City);
Property(p=>p.Addr.ZipCode);
Actually, I could not use "ComplexTypeConfiguration" instead of EntityTypeConfiguration because I would loose my chance to use HasKey, HasRequired etc.

asp.net mvc model the same as (database mapped) object?

I have the following setup: fluent nhibernate + asp.net mvc 4.
I have a seperate project in VS where all my objects are stored, these objects are directly mapped to the database.
However, to display data from these objects in the views, I need 'models'.
Do I need to create new model objects, based on these database mapped objects, or can I just pass these database objects as a model to the view? (is this a good idea?)
Thanks!
In my opinion you should create additional ViewModel classes. If some changes are to be made to the data that get displayed, it's easier to just modify these models; your domain mappings will not be affected by some particular "rendering" circumstances.
Another advantage would be that you can decorate the properties with formating attributes, without enforcing these settings on future projects that depend on your domain.
For example, say you have the following Customer class in your base project:
public class Customer
{
public string Name { get; set; }
public string Address { get; set; }
}
You can add a [Required] attribute on the Name property to make it mandatory. If for a particular project you need to also make the Address property mandatory, you would decorate it with another [Required] attribute. If you directly use the domain model classes, you will enforce that the Address property would always be required, even though the project requirements would not state that. This can be further extended to different validation attributes and also additional data that you may want to sent to the view along with the model (such as composite fields).
This is largely a design decision that depends on the size of the project, etc. Without getting into too much detail, the short answer is yes, you can use your database objects/models directly in your Views.
Sometimes it may be desirable to create specific view models if you only want to show a subset of the fields, or do different validation than the database in your View. You can then can validate this view model in your controller and if everything is okay, map it to your nHibernate models.

Storing an Exception object in Entity Framework

We are looking at adding an Exception property to one of our models that is currently mapped using Entity Framework code first.
Is there a way to map a property of type Exception directly somehow, perhaps by making it binary serialized in the database, thus maintaining a type-safe model class?
I assume I could make this work somehow by implementing two properties in the model, for instance:
public Exception Exception {get; set;}
internal byte[] SerializedException {get; set;}
Then, I would mark the real exception property as Ignore on the modelbuilder inside the context and let EF use the binary version. This is obviously very clumsy, as I would need to implement the serialization/deserialization in the getter/setter for the real exception and, as I said, I'm only assuming it's possible, but have not yet tested it.
I'm very curious if it is somehow possible to implement this using the type directly.
Unfortunately, I don't believe there is any way to do what you want with EF. The normal solution is to use the internal property like you mentioned above - just have Exception deserialize from the backing property the first time it is accessed.
It's not pretty, but EF does not expose an extension point for plugging in custom type converters between the POCO and the database, so it's the best we can do.

Using JsonIgnore on serialize, but not on deserialize; confusing with partial models

I've got a Web API project, supported by a MSSQL database containing creation and modified fields on (almost) every table. There are triggers on those fields, such that both are updated when inserting and updating a record, respectively.
Now when I'm serializing the data into JSON after a successful request, I do want to send those creation and modified fields such that the front-end making the request can do their thing with it. What I do not want, however, is that these fields can be modified when the data gets deserialized (or, POSTed back). Quite simple, you would say, just use the [JsonIgnore] attribute on the fields; put it only on the set and not on the get.
Now here is where things start to get confusing for me. All models in my project are automatically generated from an Entity Model (.edmx). As such, I cannot directly edit anything into the models themselves, but I have to generate partial models on top of them. I've seen solutions for this in other SO threads, using the [MetadataType] attribute, like this one here.
But how do I apply this (efficiently) to my case? I've been searching around, but haven't found an example on how to pull apart the auto-implemented properties in a 'higher' partial class. And even so, this would mean that I would have to create partial classes for all my models, which would be quite cumbersome. I can't imagine no-one has ever done this before, so wouldn't there be a more elegant way of pursuing this?
An example of a class would be:
public partial class Person
{
[DataMember]
public Nullable<System.DateTime> Created { get; set; }
[DataMember]
public Nullable<System.DateTime> Modified { get; set; }
}
Eventually I switched from a Model-First approach to a Code-First approach so that I would have much more control over my models.
Though, after searching a lot, I came to answer my own question. The core of this question was that I wanted to be able to set the Created and Modified fields automatically, and ignore the deserialization of the front-end, whilst still being able to send those fields through serialization to the front-end.
The solution lies in overriding the SaveChanges method in the DbContext class. An excellent example of this is given in this SO thread: Entity Framework 4.1 DbContext Override SaveChanges to Audit Property Change. So all courtesy goes to James Pogran for sparking the idea in my head, and solving the problem in that way.
What he does is checking in what way the DbEntity is changed. He sets the Created and Modified fields according to whether the entry is being added or modified, and subsequently calls base.SaveChanges in order to continue normal operations.

Categories