I am getting Nhibernate Session closed exception with asp.net mvc telerik ajax grid. The grid is bound to an entity Sale that has a related entity User. The exception thrown is when trying to access the User entity. I have used the fetchMode to eager load it but I still get the same exception. This exception only occur if I switch between the grid pages multiple times. Anyone encountered this issue?
The code for that data access is as follow:
public IList<Sale> List()
{
var manager = new ManagerFactory().GetSaleManager();
var iCriteria = manager.Session.GetISession().CreateCriteria(typeof(Sale))
.SetFetchMode("AspnetUser3.Agents3", FetchMode.Eager);
return iCriteria.List<Sale>();
}
The code that try to access the related object in the object graph is as follow:
AgentId = sale.AspnetUser3.Agents3[0].Id,
The exception thrown
NHibernate.Exceptions.GenericADOException: could not load an entity: [SalesEntry.Data.Model.AspnetUser#7aaabf99-d77d-4edf-b949-9c4c0f3e85d8][SQL: SELECT aspnetuser0_.[UserId] as column1_12_0_, aspnetuser0_.[UserName] as column2_12_0_, aspnetuser0_.[LoweredUserName] as column3_12_0_, aspnetuser0_.[MobileAlias] as column4_12_0_, aspnetuser0_.[IsAnonymous] as column5_12_0_, aspnetuser0_.[LastActivityDate] as column6_12_0_, aspnetuser0_.[ApplicationId] as column7_12_0_ FROM [dbo].[aspnet_Users] aspnetuser0_ WHERE aspnetuser0_.[UserId]=?] ---> System.ObjectDisposedException: Session is closed!
Object name: 'ISession'.
It's happening because User is being lazy loaded and you're likely seeing a situation where the session is being closed before the User object is loaded. Then when the Grid accesses the User reference you get this exception. Make sure you're following the Unit of Work pattern.
Also you may want to use a Model class to bind to your grid, rather than the entity directly. That way you control what kind of access is done and you avoid having unexpected changes to your entities/database.
Related
I am binding a task in ews.
In Microsoft docs it says:
"Binds to an existing task and loads its first class properties."
Due to the List of First Class Properties IsReminderSet is a first class property in task.
Still that property returns an
"ServiceObjectPropertyException was unhandeld:
An unhandled exception of type 'Microsoft.Exchange.WebServices.Data.ServiceObjectPropertyException' occurred in Microsoft.Exchange.WebServices.dll"
ews.Task task = ews.Task.Bind(service, ID);
if (task.IsReminderSet)
{
//do something
}
As a start make sure you using the latest version of library from github https://github.com/OfficeDev/ews-managed-api. The other thing you can do is enable tracing https://blogs.msdn.microsoft.com/webdav_101/2015/05/03/ews-best-practices-tracing-and-logging/ this will allow you to see exactly what the server is actually sending back to. Its possible especially if mailboxes has been migrated that these properties can be null on the server side (due to the migration method used).
I have created a page asp.net MVC for inserting records to database where i am giving a preview button to see how the data will looks on client side before saving it. I am using session to pass model to the preview page. On preview page i have created a button which will save the model in session to database but it is throwing exception "An entity object cannot be referenced by multiple instances of IEntityChangeTracker".
I am using the same dbContext. I had tried many solutions given by users but they are not working for me. I have attached the part of the code that's throwing exception. Please see where I am doing wrong.
Here is the code where I am saving record
var model = Session[Constants.SessionVariables.ProjectModelForPreview] as Project;
if (create != null)
{
if (model.Id == 0)
{
if (model.IsFeatured)
{
foreach (var item in dbContext.Projects.Where(p => p.IsFeatured == true))
{
item.IsFeatured = false;
}
dbContext.SaveChanges();
}
dbContext.Entry(model).State = EntityState.Unchanged;
dbContext.SaveChanges();
TempData["SuccessMessage"] = "Project created successfully.";
return RedirectToAction("Index");
}
}
Your controller, and therefore your DbContext, is instantiated per request. So your application follows this flow:
Request 1 instantiates DbContext 1.
You load an entity through DbContext 1. This entity is being tracked, and the entity itself holds a reference to DbContext 1.
You store this entity in the session, keeping the old DbContext alive. This works, because the default session state works InProc, and not by serialization.
Request 2 comes in, DbContext 2 gets instantiated.
The entity is retrieved from the session.
You try to save the entity, still being tracked by DbContext 1, through DbContext 2. This throws.
Now for the solution there are various approaches:
Don't save entities in the session at all. Persist them, and look them up again in successive requests.
Save entities in the session by manually serializing them.
Load the entity with .AsNoTracking().
Let's ignore the original problem for now,it will be solved once you refactor the code
1)if for some reason you are using the same context across request ,stop.
(I don't think you do though).
2)Don't save tracked entities in the Session*
Search on google to see how EF tracks changes.
3)Read 1 and 2 again
*Use .AsNoTracking() or project your entity in a new model and save that in the session
I currently have an ASP.NET Web Api 2 application which, for the purposes of this question, manages 'Items'. ASP.NET Identity 2 is used to provide authentication for requests, and the data is handed by Entity Framework 6.
My aim is for the item's Owner property to be set automatically to the user who authenticated the POST request. Below is the code so far:
public async Task<IHttpActionResult> PostItem(Item item)
{
var userId = User.Identity.GetUserId();
var user = await UserManager.FindByIdAsync(userId);
// Set the Owner to the currently authenticated user
item.Owner = user;
db.Items.Add(item); // Exception Thrown Here
await db.SaveChangesAsync();
...
}
However, when the method is called, the following exception occurs. The current userId and user are being found correctly, yet there is still an issue adding the Item once its Owner property has been set.
A first chance exception of type 'System.InvalidOperationException'
occurred in EntityFramework.dll
Additional information: An entity object cannot be referenced by
multiple instances of IEntityChangeTracker.
The problem is that you're trying to track the same entity using two different contexts and that doesn't work. maybe you should look in your code and see which of your entities is being tracked by two context, It is possible since you are using a global variable (db) as a reference to your context.
I have a method in my generic repository:
public IQueryable<T> Query<T>() where T : class, IEntity
{
return _context.Set<T>();
}
This is method for getting user:
public User GetUser(string email)
{
return _repository.Query<User>().FirstOrDefault(u => u.Email == email);
}
Finally, I put the user to session:
AppSession.CurrentUser = UserService.GetUser(email);
In my action I need to get the current user and get collection of objects Notifications (one-to-many):
AppSession.CurrentUser.Notifications.OfType<EmailNotification>().FirstOrDefault();
But, here I get the error:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I know that Notifications not loaded when I getting User from DB.
How to say EF to load Notifications objects? I know about Include, but I cannot use it in GetUser method.
When the first HttpRequest ends after looking up your CurrentUser object, your _repository reference that the CurrentUser is expecting for additional lookups like EmailNotifications isn't available.
The exception is thrown because CurrentUser doesn't have the original object context, so you either have to attach the CurrentUser object to the new objectContext that your _repository is using, or use the easier solution of simply reloading the user through the new context that was created for your current request in the repository.
Before attempting to find the notifications in your action, add the following line:
AppSession.CurrentUser = UserService.GetUser(AppSession.CurrentUser.Email);
AppSession.CurrentUser.Notifications.OfType<EmailNotification>().FirstOrDefault();
As #Ryan said it is due to the fact that the object context is not available to lazy load in the associated notifications.
What I'd suggest is turn off lazy loading (if possible) as can cause lots of issues later and then do something like ...
var user = UserService.GetUser(AppSession.CurrentUser.Email);
user.Notifications = NotificationService.GetUserNotifications(user.Id /* or another identifier */);
AppSession.CurrentUser = user;
To do this you will require a new NotificationService, this can load (as suggested above) but also handle the execution of notifications (sending emails etc).
You should now have the notifications for that user in your Application session cache.
HTH
I have a User table, with a many-to-many relationship to an Alerts table. After creating a Membership user, I am adding some extra info into the database.
MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
if (createStatus == MembershipCreateStatus.Success) {
User user = new MidTier.Models.User();
user.FullName = model.FullName;
if (Alerts.Count() > 0)
{
var userAlerts = SetAlert(Alerts); // creates an IEnumerable of Alerts (from a list of int )
foreach (var alert in userAlerts)
{
user.Alerts.Add(alert); //add each alert to the user
}
}
userRepository.Add(user); //throwing error
userRepository.Save();
}
I get an error (' An entity object cannot be referenced by multiple instances of IEntityChangeTracker.') on calling the Add method. there are lots of references about this error on the net even here on SO, but after reading all those comments and suggestions, I a havent found a solution or the reason I am getting this error.
there are lots of references about
this error on the net even here on SO,
but after reading all those comments
and suggestions, I a havent found a
solution or the reason I am getting
this error.
If you really searched you should already know that error says you that some entity in object graph is already attached to other context. Because of that your code sample is mostly not related. The real important code is wrapped in your methods - probably SetAlerts and userRepository.Add. If these two methods use internally context and they don't use the same instance it is the reason for your exception.