1

I've got an issue with serializing proxy classes with lazy loaded navigation properties. The error which I catch looks like this:

ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

The serialization fails when Newtonsoft.Json tries to do it:

JsonConvert.SerializeObject(objectGraph, _settings)

For example, the objectGraph is something like:

class Locations {
    public virtual ICollection<Department> Departments;
}

And Department property cannot be loaded because the context is already disposed.

Question:

How can I prevent loading of lazy loaded properties by the JSON serializer?

I tried to use #1 contract resolver, #2 type converter but they didn't help. It seems like the object loaded fully before apply those resolvers or converters. I suppose there should be some way to prevent from loading lazy properties.

Any ideas?

For those who is interested in the layout class code: git repo.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Alexander Goida
  • 305
  • 1
  • 11
  • Can you add the code you pass data into JsonConverter? is it a Queryable or a list of entities? – Khai Nguyen Oct 10 '18 at 08:39
  • It's just entity. I'm not passing directly. I've attached the layout through log4net configuration. type converters or contract resolvers are set to Json.NET in a standard way. Later in the code I'm calling log.Debug(entity). This is as simple as this. If time allows I try to simulate the issue on small project later. – Alexander Goida Oct 10 '18 at 08:47

1 Answers1

1

Have you tried using [yourQuery].AsNoTracking().FirstOrDefault() when querying the data from the Database.

You will then get the "real" object instead of a proxy object(https://stackoverflow.com/a/13077670/8336973).

When no tracking is active the lazy loading will not happen and everything that is not loaded will be NULL and not cause the ObjectDisposedException.

RedFox
  • 457
  • 3
  • 15
  • This is impossible unfortunately. The idea is that no code changes should be done in the way how production code is working. Only logging should be added. So I cannot change the way, how data is queried. But I've got a workaround by using a projections for logging. Instead of passing a proxy, I pass an anonymous object `new { id = entity.Id, depIds = entity.Deps.select(d => d.Id).AsArray() }` where I build a new object without lazy loading. – Alexander Goida Oct 10 '18 at 09:39
  • The only other thing that came to my mind was using the `DBContext` `context.Entry(entity).CurrentValues.ToObject()`, but then you would need the `DBContext` and I'm afraid you don't have it, since you're getting the `ObjectDisposedException`. So I think using the anonymous object or mapping the proxy to another type (with [AutoMapper](https://github.com/AutoMapper/AutoMapper)) is the best solution :) – RedFox Oct 10 '18 at 14:34