简体   繁体   中英

Lazy & eager Loading MVC 5

I have the following code and i try to get all students (with UserTypeID =2)

using SchoolData;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace SchoolAPI.Controllers
{
    public class StudentsController : ApiController
    {
        public List<User> Get()
        {
            using(SchoolEntities DB = new SchoolEntities())
            {
                var L = DB.Users.Where(u => u.UserTypeID == 2).ToList();
                return L;
            }
        }

    public User Get(int id)
    {
        using(SchoolEntities DB = new SchoolEntities())
        {
            return DB.Users.Where(u => u.UserTypeID == 2).FirstOrDefault(u => u.UID == id);
        }
    }
}
}

when i run this code with lazy loading enabled i try to get all students through function Get() it throws an error :

"Message": "An error has occurred.",
    "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
    "ExceptionType": "System.InvalidOperationException",
    "StackTrace": null,
    "InnerException": {
        "Message": "An error has occurred.",
        "ExceptionMessage": "Error getting value from 'City' on 'System.Data.Entity.DynamicProxies.User_43D4A249734A75DBA5AC314F4FE462E834BDC252CC9384BF940FE65C74CE3D08'

and

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

and when i try to disable lazy mode and re-run it gets the objects correctly but with some additional unneeded parameters as following:

{
    "City": null,
    "CourseDetails": [],
    "StudentsCourses": [],
    "UserType": null,
    "UID": 2,
    "FName": "Ahmed",
    "LName": "Mano",
    "Birthdate": "1995-05-27T00:00:00",
    "CityID": 1,
    "UserTypeID": 2
}

and i don't neither need that CourseDetails,StudentsCourses,City nor UserType

When the object gets serialized to json, those properties are serialized weather you use them on the client or not. Since serialization occurs after you exit the using block, the properties are accessed after the context is disposed. You can do one of three things:

  1. Mark the unused properties with the [JsonIgnore] attribute. See here for details

  2. Create a second class that only contains the properties you need in the client and use Select to project the User to this new more specific object. Or use auromapper to do the mapping automatically. With regards to auromapper this might be a good article to get you started

  3. Create one context per controller, initialize it in the contractor, and only dispose it in an override to the controller dispose method. This will ensure that the context is available during serialization.

From a performance standpoint 2 is best as you only send exactly what you need and you have a lot more flexibility to tailor the output to each action (maybe other actions require those fields). 3 is the simplest to implement, but you are sending a lot of data you don't need, and hitting the database needlessly. 1 offers and easy fix, until someone else adds a new property to the model, also, you might end up with data in the client that not only you don't need, but that should not reach the client (passwords, other sensitive info that might be added to the model)

Titian Cernicova is completely right, I just want to add one thing: if u return an Entity Object from a WebAPI controller u may have memory issues and possibily a Memory Leak on your server, don't ever do that

So, a good practice is to create a data transfer object with properties you need like:

public class DtoUser
{
    public int UID { get; set; }
    public string FName { get; set; }
    public DateTime Birthdate { get; set; }
    public int CityID { get; set; }
    public int UserTypeID { get; set; }
}

Cast your Entity Object into this and return.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM