4

I'm using a library (Telerik) for ASP.NET MVC 3.

I've a problem with all functionnalities which needs to return by AJAX some data:

I'm using EF4 to connect my database, and I've(and need) navigation properties in both ways(Imagine, a User which have some Posts and one Post have an User).

The problem is that the library is using the JavaScriptSerializer, which encodes data with JSON.

The error that I get

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Employee_34048F4F6A98297F826C798A27640C7383E95E8EA8282EC8A5F738FA0C77CBC3'."

Exception, which is right, because the parent has reference to its children, and children have reference to its parent.

I've already found some workaround, but nothing which fully satisfy me:

  • Use data server binding: cannot, the functionnality has to work in ajax(Its a pager for grid, which loads the next elements when the page has been scrolled to the end)
  • Use an anonymous objects: not flexible, because if I've a field in addition in the database, I must add it in all my anonymous object, and in addition, if I need to have a sub-collection which I want, it's boring to also create objects for all element of this sublist.
  • Use ViewModel: Almost same problem, if I've one more field, I must add this fields on all viewModel, and I've to create an view model for all my 60 views, with exact same fields than my model, ...
  • Use the NonSerializedAttribute : I don't know how to put in my T4 template which generate my POCO objects, and I'm not sure it will works: sometime the main object is the children, sometimes it's the parent, the empty relations has to be another one.

I had almost the same problem with WCF, and I created a serialized which knows handling circular reference, can we do the same here? Or is there a way to manage this?

If not, I suppose that the best way is to use "ViewModel", but is there a way to accelerate those creation? Like a generic object, which takes in the constructor the EF object and remove circular reference? anything else?

Thank you very much

abatishchev
  • 98,240
  • 88
  • 296
  • 433
J4N
  • 19,480
  • 39
  • 187
  • 340

1 Answers1

5

Actually, rather than [NonSerialized], it is [ScriptIgnore] that you would need. I would approach this from one of 2 angles, though:

  1. use RegisterConverters and write a custom converter that specifies all the properties except the parent one (this could probably be automated too, maybe using a bespoke class-level attribute like [SkipSerialize("Parent")] added in a partial class - that is probably over-complicating things, though).

  2. simply: don't serialize the EF POCO, but instead use a DTO - it sounds like this is what you mean in your ViewModel answer. Personally, I have no issue with having an "entity" (EF/POCO) version of a class and a very similar but different DTO version - their intent is different, and in my mind it doesn't violate DRY.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I support the ViewModel approach, too. It seems redundant and irritating at first, to create copies of the entities. So you mess with different serialization attributes or converters to try and get the right outcome, but run into a situation where two (or more) different views need different things serialized. After failing that, you create a ViewModel and use something like AutoMapper (http://automapper.codeplex.com/) to copy data to and from your entities and view models, and suddenly view models make sense. – moribvndvs Dec 14 '11 at 09:22
  • @HackedByChinese absolutely; all too often I see people fighting with a model trying to get it to align with some specific serializer, when there would be less complexity (and probably less code) if they chose a DTO (/ViewModel) representation that **fits the serializer**. – Marc Gravell Dec 14 '11 at 09:26
  • I found an interesting VS add-in that is intended for XAML, but has a feature for generating view models/dto from an existing class. Nice. http://karlshifflett.wordpress.com/xaml-power-toys/#FeatureSet – moribvndvs Dec 14 '11 at 09:31
  • It's what I was thinking, ViewModel(or DTO) seems to be the way to choose. I'm looking about the AutoMapper. What is the good approache with this tools? Reproduce the same structure than the EF object? Because by example, if I display a product, I still need to display it's category name with it. What will differ from your EF entity and the DTO ? – J4N Dec 14 '11 at 10:38
  • @J4N generally: no parent properties; no lazy loading; maybe some denormalization (adding in a name or some natural key to something that was otherwise only known by db id, but which doesn't warrant a full object) – Marc Gravell Dec 14 '11 at 10:48
  • @Marc Gravell: Okay, but the lazy loading by example, it's the datacontext which manage it, not my POCO object. Another mind: While my EF model are POCO , why can I not only create a EF instance mySelf, which I fill myself from the EF object? just setting "Null" to some properties? Since I need exactly same fields in the DTO and the POCO object. – J4N Dec 14 '11 at 10:52
  • @J4N *if* EF lets you do that, then fine - whatever works. However, one of the EF POCO models is where you use `virtual` properties, and EF silently subclasses your types (replacing them with a proxy to do things like lazy loading). Sometimes what you see is not what you get. – Marc Gravell Dec 14 '11 at 11:11