2

I am confused with an error that Action returns me. I have a code in my manager:

public class AddressesManager
    {

     private SiteDBEntities entityContext;

     public Addresses GetAddress(short id)
            {
                entityContext = new SiteDBEntities();
                var addressList = entityContext.Addresses.Where(a => a.Id == id).FirstOrDefault();
                entityContext.Dispose();
                return addressList;
            }
}

And action that call this function:

 [HttpPost]
        public ActionResult LoadAddress(short id)
        {
            AddressesManager mngr = new AddressesManager();
            Addresses address = mngr.GetAddress(id);
            return new JsonResult() { Data = address };
        }

And jQuery code which calls this action:

$.post("/Cart/LoadAddress", { id: id })
         .success(function (data) {

             console.log(data);
         })
    .fail(function (e) { console.log(e) });

Action is running, but I always getting 500 error with this code:

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

As I understood the problem is with entityContext, but why this happens? I already executed data from DB and I don't need connection anymore...

EDIT:

Thit is my Address model. It autogenerated by EF:

public partial class Addresses
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string State { get; set; }
        public string Country { get; set; }
        public string Warehouse { get; set; }
        public string FirstName { get; set; }
        public string SecondName { get; set; }
        public string Phone { get; set; }
        public short DeliveryType { get; set; }
        public System.Guid UserId { get; set; }
    
        public virtual DeliveryType DeliveryType1 { get; set; }
        public virtual Users Users { get; set; }
    }
12
  • I checked data in address variable - everything OK and data present here Commented May 13, 2016 at 13:50
  • this error happens because the Addresses Class has some virtual properties, and it is Converted to JSON , it wants to get those virtual properties too. Commented May 13, 2016 at 13:50
  • Yes, you are right. This is it. So what is the way to avoid this error? Manualy map the model? Commented May 13, 2016 at 13:52
  • Try this entityContext.Configuration.LazyLoadingEnabled = false; Commented May 13, 2016 at 13:54
  • Agreed with @Arvin, json serializer is trying to access to some navigation property, and due to that, lazy loading is getting triggered. Check my answer: stackoverflow.com/questions/30744530/… Commented May 13, 2016 at 13:56

6 Answers 6

1

The error happens because your Address class has 2 virtual properties: DeliveryType1 and Users.

When you convert your address to JSON, it will try to access those virtual properties. However, at that time, your context are disposed already.

To avoid this problem, you shouldn't return the EF auto-generated class directly. Instead, create a DTO object (Data Transfer Object) containing only some fields you need, map it with the EF object, and return it. For example:

public class AddressesDTO
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string State { get; set; }
    public string Country { get; set; }
    public string Warehouse { get; set; }
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public string Phone { get; set; }
    public short DeliveryType { get; set; }
    public System.Guid UserId { get; set; }
}

Then, map it:

public Addresses GetAddress(short id)
{
    entityContext = new SiteDBEntities();
    var addressList = entityContext.Addresses.Where(a => a.Id == id).FirstOrDefault();

    // Create DTO object
    AddressesDTO address = new AddressesDTO();

    // Map it
    address.Id = addressList.Id;
    address.Title = addressList.Title
    // Go on, it's quite long...

    entityContext.Dispose();
    return address;
}

However, as you can see, the mapping process is very boring. A better way is using Automapper.

Sign up to request clarification or add additional context in comments.

Comments

1

If you want to use your entity data model then I suggest you to take a look to my answer in this post.

Now, what I would do is create a DTO to get only the data you need to pass to your View, like was proposed by @AnhTriet. To avoid map by yourself each property every time you need to project your query to your DTO, I suggest to use Automapper. Let me show you how would be your solution if you decide to use it:

public class AddressesManager
{
    public Addresses GetAddress(short id)
    {

        using(var entityContext = new SiteDBEntities())
        {
            var address = entityContext.Addresses
                                       .Where(a => a.Id == id)
                                       .ProjectTo<AddressDTO>()
                                       .FirstOrDefault();
            return address;
        }
    }
}

About ProjectTo extension method.

3 Comments

Thanks for your post. I currently study in courses and I heard from guys from my group about bad performance when they used Automaper. So they decide to use custom mapping.
Your comment about DTO was usefulest thing for me. Now I can understand program architecture more clear
You're welcome ;). About Automapper, I have to say at least in my case I haven't had that kind of issue. But I think all depends in the way you create your queries because at the end are translated to SQL, and if you do something inefficient in your Linq queries or map unnecessary data, of course that will affect your performance.
0

Do you have a navigation (child) property in your Address class? I get the feeling that you're trying to access this child property after the DbContext has been disposed of, as child properties are lazy-loaded by default.

Can you post the code of your Address model?

1 Comment

Is a good practice to use EFcontext.Dispose() in destructor of my manager to avoid porblem wiht lazy loading?
0

I think you should add attribute [JsonIgnore] to virtual properties of Addresses Class.

class Addresses
{
    public int ID { get; set; }

    [JsonIgnore]
    public virtual Something Something { get; set; }
}

Comments

0

Addresses should be lazy-loaded in your case. So you are trying to access disposed data and Entity Framework tries to use disposed context and that gives an exception.

Maybe you need to attach your addressList to current context in order to enable lazy-loading

var addressList = entityContext.Addresses.Where(a => a.Id == id).FirstOrDefault();
entityContext.Addresses.Attach(addressList);

Comments

0

When you are returning a json record in MVC you need to add AllowGet like so in your controller:

return Json(new { data= address }, JsonRequestBehavior.AllowGet);

With this in place you should be fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.