This question has been asked a lot of times. I think I solved my problem but since I am a beginner and still learning I need your reassurance.
I made a Extension method for the Logged In User But when I use it in my Controller it gives me the error in title.
System.ObjectDisposedException: 'The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.'
So I searched and experimented and adding this line of code in the controller solved my problem.
db.Users.Attach(LoggedUser);
However I am not sure if my answer is correct, since a lot of answers about this question were to disable the Lazy Loading but I didn't end up using it.
Something like this.
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
Here is my Extension method:
public static ApplicationUser GetLoggedInUserInDB(this System.Security.Principal.IPrincipal _User)
{
using (var db = new ApplicationDbContext())
{
string userId = _User.Identity.GetUserId();
var LoggedUser = db.Users.Find(userId);
return LoggedUser;
}
}
My Controller:
public class MainPageController : ApiController
{
[Route("Personal_Project/Main_Page_Personal_Project/UserUnfo")]
[ResponseType(typeof(string))]
[Authorize]
public IHttpActionResult GetUserInfo()
{
using (var db = new ApplicationDbContext())
{
var LoggedUser = User.GetLoggedInUserInDB();
//db.Users.Attach(LoggedUser); // This is what I added to solve my problem.
return Ok(new UserInfoModel
{
Name = LoggedUser.UserName,
Reputation = LoggedUser.Reputation,
UserLevel = LoggedUser.UserLevel
});
}
}
}
So is 'My' solution here good? Just adding:
db.Users.Attach(LoggedUser);
Is it legit or this is not how we solve this problem. Any advice will be greatly appreciated
Added as requested:
StackTrace:
ex.StackTrace " at System.Data.Entity.Core.Objects.ObjectContext.get_Connection()\r\n
at System.Data.Entity.Core.Objects.ObjectQuery1.GetResults(Nullable
1 forMergeOption)\r\n at System.Data.Entity.Core.Objects.ObjectQuery1.Execute(MergeOption mergeOption)\r\n at System.Data.Entity.Core.Objects.DataClasses.EntityReference
1.Load(MergeOption mergeOption)\r\n at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.DeferredLoad()\r\n at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.LoadProperty[TItem](TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject)\r\n at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.<>c__DisplayClass7`2.b__2(TProxy proxy, TItem item)\r\n at System.Data.Entity.DynamicProxies.ApplicationUser_3D8410FBA1701532D53558B4E07B366CC45F4901DA609FCE10D652D704EEDD3C.get_CarGame()\r\n at PersonalProject.Controllers.MainPageController.GetUserInfo() in C:\Users\Jack\Desktop\PostPersonalProject\PersonalProject\PersonalProject\Controllers\MainPageController.cs:line 32" string
You're getting exception because of this: get_CarGame()
.
Code inside original post doesn't match your actual code.
Somewhere inside actual MainPageController.GetUserInfo
you're trying to read ApplicationUser.CarGame
. And yes, this is lazy loading issue.
GetLoggedInUserInDB
returns instance of proxy class, derived from ApplicationUser
, and disposes original context. When GetUserInfo
tries to get CarGame
property value, proxy attempts to read it from database, using disposed context. As a result, exception is being thrown.
If you really need CarGame
inside UserInfoModel
:
Select
) to retrieve user info as UserInfoModel
in place. In this case there is no need in GetLoggedInUserInDB
method at all.Anyway, attaching LoggedUser to another context is not a way to go.