System.ObjectDisposedException when trying to list an object - c#

Trying to fix this error
public ActionResult MyEvents()
{
Personne personne = (Personne)Session["User"];
personne.Evenements.ToList();
return View(personne);
}
Got the System.ObjectDisposedException and Evenements is null
Using many to many relation between Personne and Evenement so cannot read the join table in the db.

The problem is that the Evenements are probably being loaded using lazy loading (i.e. not retrieved until the property is accessed).
When you are coding web applications the connection used to fetch information is usually closed when the HTTP request ends.
Thus when you on the second request try to access Evenements property the connection have been closed. And you therefore get the ObjectDisposedException.
You can activate eager loading by using the Include method: http://www.entityframeworktutorial.net/EntityFramework4.3/eager-loading-with-dbcontext.aspx
That way the property have been loaded and stored for all future requests.

Related

EF6 The operation cannot be completed because the DbContext has been disposed

I know there are a bunch of these error messages in SO because I've read them all, sadly to no avail.
I have a WebApi controller that is getting a set of 'Persons' via EF6 from a SQL Server DB. Very simple example
Things I've tried so far, with no success:
- Disabling proxy generation
- Disabling lazy loading
- Adding Includes to get child refs with both linq and string parameters.
- Replacing the using with try/finally -> dispose of DbContext.
- Remove "application/xml" from supported media types via WebApiConfig
- Ensured circular dependencies are attributed with [IgnoreDataMember]
- ... More I cannot remember :)
Here is the PersonController Get method:
public IEnumerable<Person> Get()
{
try
{
IEnumerable<Person> persons = null;
using (PersonContext entities = new PersonContext())
{
entities.Configuration.ProxyCreationEnabled = false;
entities.Configuration.LazyLoadingEnabled = false;
persons = entities.Persons.Take(5);
}
return persons;
}
catch(Exception ex)
{
...
}
}
Now no exception is thrown at ANY point in the controller. The exception is however displayed in the browser:
"<Error><Message>An error has occurred.<\Message>
<ExceptionMessage>The 'ObjectContent`1' type failed to serialize the response body for content type 'application\/json; charset=utf-8'.
<\ExceptionMessage>
<ExceptionType>System.InvalidOperationException<\ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.<\/Message>
<ExceptionMessage>**The operation cannot be completed because the DbContext has been disposed.**<\/ExceptionMessage>
<ExceptionType>System.InvalidOperationException<\/ExceptionType>
<StackTrace> at
System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
The error tells me that something else is trying to read the context after the using clause has popped but I'm at a loss to know what that could be? As you can see I copy the enumerated data from the context into the local list before returning that. Got me stuffed!
Any suggestions appreciated.
The line
persons = entities.Persons.Take(5);
is a definition of how to retrieve data, but the data itself is not yet retrieved at that point ('delayed execution'). The line is located inside the using(){} construct, so right after that the DbContext is disposed. A while later the View needs the data, the DbContext is consulted, but it is closed already.
Solution:
Retrieve all data before closing the DbContext. This is frequently done using ToArray() or ToList(), whichever suits you best.
So the line should be e.g.:
persons = entities.Persons.Take(5).ToArray();
persons = entities.Persons.Take(5).ToList() or ToArray.
You are actually closing the connection before fetching the data.
If this doesn't work, try remove using clause for dbcontext just to check whats happening.

Put Attempted on document using non current Etag error

I am going through the popular Pro ASP.NET MVC 5 book and building the Sports Store application, but I am using RavenDb instead of Entity Framework.
Initially, I created the Product records in Raven through the local API (not through code). I gave the records a manual Id and created the json fields and values for each product - 9 in total. I then wrote the parts of the application that loaded these products and everything worked totally fine. The data returned exactly as I expected every time.
However, when I got to the part of the application that allowed users to create new records through the MVC interface, I got a crash when calling the SaveChanges() function on IDocumentSession.
This is the full text of the error:
Server Error in '/' Application.
PUT attempted on document 'products/9' using a non current etag
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Raven.Abstractions.Exceptions.ConcurrencyException: PUT attempted on document 'products/9' using a non current etag
This is the full text of the Save function I am calling:
private readonly IDocumentSession _session;
public void Save(Product product)
{
_session.Store(product);
_session.SaveChanges();
}
_session is initialized in the repository constructor like this:
public ProductRepository()
{
_session = RavenDbStoreSingleton.DocumentStore.OpenSession();
}
And this all interacts with a singleton for DocumentStore:
public class RavenDbStoreSingleton
{
private static readonly Lazy<IDocumentStore> Store = new Lazy<IDocumentStore>(CreateStore);
public static IDocumentStore DocumentStore => Store.Value;
private static IDocumentStore CreateStore()
{
IDocumentStore store = new DocumentStore()
{
Url = "http://localhost:8080",
DefaultDatabase = "SportsStore"
}.Initialize();
return store;
}
}
So my guess is that my manually entering ALL of the first records and then trying to save new records somehow caused this error, but I'm not sure why Raven can load the Products but can't seem to save without hitting conflicting Ids. I even went and increased the Hilo for the Products (which is the only document type) from 32 to 64, but that didn't affect anything.
Update: I noticed that each time I got this error, it conflicted on a higher Id than it did previously. I was able to keep attempting to save until the error no longer occurred, at which point the Id generated was Products/65, which makes sense as I had modified the Hilo from 32 to 64. It did not try to generate Products/10.
However, I don't understand why modifying the Hilo halfway through my 9 crashes didn't make Raven start generating at Products/65 and instead it kept trying to generate already taken Ids.
The reason why it did it was that it was caching the hilo value, and until it run out of the hilo range, it had no reason to request a new range.
The hilo doesn't go to the server on every request.

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown in angularjs

I have spent couple of weeks for this issue. but still I can't resolve this issue.
i am calling a web API service by using http in angularjs
$http({
method: 'GET',
url: rootUrl + '/api/Project/ProjectList',
headers: {
'Content-Type': "application/json; charset=utf-8"
}
}).success(function (response) {
$scope.ProjectList = response;
}).error(function (response, errorCode) {
if (errorCode == 444) {
}
})
I have put break point in server and client side coding.
When i call the service, the server side method hit quickly
My server side method (am Using MVC WEB API with entity framework)
[ActionName("ProjectList")]
[HttpGet]
public IList<Project> ProjectList(Project projectModel)
{
return objIProjectService.ListOfProject();
}
I checked, the service return 8 records( 8 rows from database) with a break point in objIProjectService.ListOfProject(); this line.
everything is going good. But my (response) http.success and http.error call back functions are hitting very slow.
Please see below image for the performance while i calling the http methods
Finally the http error function hit after 5 or 10 mins with this below error message.
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown
This is the problem. Please let me know how can i solve it?
Actually am did something for this issue.
I have cleared the temp folder - not working
I have restart the Visual studio and clean the solution, restart my system and repairing visual studio.- not working
But if I have deleted some rows in database (am using sql server 2008 r2 ), then it's working.
For example, if my database table have below than 7 rows, then it's working fast without that error.
But if my table have more than 8 rows, then it's working very slowly and threw the error?? Why??
re
could you please share your solution if you stuck this issue.
I think the problem is that the serialiser is accessing all the related properties on your project Class, so rather than directly returning the Entity Framework Class, create a new class to represent the data that you wish to send through your api (research further into DTO classes for further information)
You can use the Select Linq method to get a list of your new dto class populated with the data from your EF call.
var projects = objIProjectService.ListOfProject();
return projects.Select(p => new ProjectDTO() {
ID = p.Id
//... other properties of DTO class
}).ToList();
even better, if you put this select method, into your EF query (i.e. context.projects.Select(/* select info here */).ToList(), you can make sure EF is only bringing back the fields that you need
when building an API always check the json/XML response, make sure the serialised data contains what you were expecting it to produce. with entity framework this response can end up huge as it navigates through all the related tables pulling out all the linked information and then attempting to serialise it.
as a personal preference I always prefer to return an IHttpActionResult it allows you to manage what is being sent back to the client especially when there are issues, the controller has a number of methods you can use to createthis i.e. OK(), BadRequest(), InternalServerError() ...
Open Sql Server Profiller and watch EF generated sql queries and results. And then try execute on sql window this raw queries. Probably you'ill understand after this.
The issue here is that the serializing of the information is taking to much time. You are accessing all the related classes of your project class, which may cause a significant damage when dealing with memory aspects.
you can resolve this in two ways:
One is to return your promises and then fetch the data:
return $http({
method: 'GET',
url: rootUrl + '/api/Project/ProjectList',
headers: {
'Content-Type': "application/json; charset=utf-8"
}
}).then(function (response) {
A second option will be in the code, using Entity framework or linq queries.
Use select queries to lower the burden on the server side and client side as follow:
var projectsQuery = from p in ProjectModel as pm where pm.Id = p.Id select p.SomeValue
return projectsQuery
this way you will be able to lower the burden of the data serializing and might possibly avoid the outOfMemoryExcexption.
There is no need in opening the Sql Profiler here since the data from the server side comes at a reasonable time.
The HTTP specification doesn't impose a specific size limit for posts.
The problem with GET queries is that the parameters are embedded in the URL, which is limited in size (this limit is browser and server dependent).
Don't use a GET query for big data use a POST one.
there is another topic If you are using MVC and you working on big data,
you need to use this one.
<appSettings>
<add key="aspnet:MaxJsonDeserializerMembers" value="150000" />
</appSettings>
or
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1000000" />
</requestFiltering>
</security>
from : MSDN
I hope these will solve your problem.
Going further with Chris Warnes suggestion and describing the possible reason.
Let me guess... you use entity framework with lazy loading enabled. So during serialization every navigational property you have is loading data lazily and recursively sometimes. For instance: Project contains Worker which contains reference to same Project in some navigational property such as WorkerProjects.
Serializer tries to make sense out of it, but it cannot, without some hint.
the easiest way to check what is going on, is to disable entity framework lazy loading and get that breakpoint there, right after ToList() and just before the return.
BTW. Serializing this kind of structure to JSON is - kind of - impossible. You need to have external mechanism (such as cycle.js is using XPath to encode such a reference) to deal with duplicated references and cycles.

Class scope in a web application

I have a question regarding the scope of a class that I created in relation to a web application.
My class is CCourseInfo and I create it as a private member of one of my web pages Enrollment.
In the Page_Load method, there is a database call to load the table data in the class member, DataTable. This DataTable is bound to a gridview.
This is the code:
public partial class Enrollment : System.Web.UI.Page
{
private Course CCourseInfo = new Course("Courses");
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (!IsPostBack)
{
//Get the Environment Setting to determine the database to access
txtBoxEnvironment.Text = CurrentEnvironment;
DAL.setCurrentEnvironment(CurrentEnvironment);
//Get Course information from database
CCourseInfo.getData();
CourseGridView.DataSource = CCourseInfo.TableInfo;
CourseGridView.DataBind();
}
}
}
I want to implement Paging.
This method works but I have to get the data again to populate the DataTable in the CCourseInfo class.
protected void CourseGridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
CourseGridView.PageIndex = e.NewPageIndex;
CCourseInfo.getData();
CourseGridView.DataSource = CCourseInfo.TableInfo;
CourseGridView.DataBind();
}
My question is: Why do I have to get the data again? I set the DataTable in the Page_Load method and declared the class under the Enrollment class. Shouldn't the data still exists in the DataTable? How can I change my design so that I only have to get the data once?
Thanks,
You have to get the data again because ASP.NET (and in general, web pages) are stateless objects - this means that after each execution of your page, the page is cleaned up and all of its state is deleted. You'll have to recreate all of it when a new request comes in for the same page - the same page class will be instantiated again and you'll go through the page life cycle once more from beginning to end.
If you're not familiar with the page life cycle, here's an SO question / answers with quite a bit of detail - this will help you understand better what's going on during a request.
There are some things you can try (not an exhaustive list):
Cache all your records from the database in a cache server or in session state. If you have a lot of records, this could use a lot of memory (for each user) since all pages are loaded at once - you don't hit your database every time to query data. Caching speeds things up quite a bit but you may showing outdated data to the user - another user may change the data. It's also fairly tricky to properly handle cached data (when to remove it, when to fetch a fresh copy, etc.)
You can query only records for a single page - this results in lower data traffic between the web server and the database. You also have to query data every time the page changes, since you don't have more than the current page.
You can query all data and then send it to the client side and perform all paging in the browser. This generates a lot of traffic, since you have to send all pages to the client, whether the user wants to look at them or not. Paging is much faster this way but the browser uses a lot of memory and getting the data to the client can take a long time, depending on network speed.
The best solution is to get as little data as you can get away with (one page for the grid) - if you have to re-query it, the database will send you as little as needed.
Ok first because Web is using HTTP which is a stateless protocol so that's why you loose a web page's state.
So you have to manage the state your self. there are many ways that you can use to manage state.
Here is how i solved this problem i saved the data that i received from database and stored the entire list in View-state. And every time there is a post-back i retrieve the data from view-state.
if (!Page.IsPostBack)
{
ViewState["data"] = MyDataset;
DataListView.DataSource = ViewState["data"];
DataListView.DataBind();
}
if (Page.IsPostBack)
{
DataListView.DataSource = ViewState["data"];
DataListView.DataBind();
}
you can also use Session state and a few other state management techniques.

Login failed for user ''. - ASP.NET MVC FormsAuthentication

My "Register" page used to work, until I started using FormsAuthentication and FormsAuthenticationTicket to login.
Now on Register, it fails when checking if an email already exists in the database, on this line
if (Global.DC.Users.Where(x=>x.Email == Email).Count() > 0)
return "The email address already exists in the database";
with this error message
System.Data.SqlClient.SqlException:
Login failed for user ''.
Does anyone know how to solve this? Thanks in advance.
Looks like the SQL login is invalid. I would check your connection string to see if that has changed, and if not, I would validate that the SQL Login and Database User is configured correctly.
Typically you may not realise this has happened if you are changing how your DataContext is being called, if you used to explicitly test it using a specific connection string, or create it with the default constructor (new ....DataContext()). Using the default constructor normally uses the design time connection string configured in the Settings.settings project item which stores the connection string name to reference in your web.config configuration file. Are you still calling it the same way?
On another note, I noticed you're calling your DataContext through your Global class. This is generally considered a bad design, and you should really consider using a unit-of-work` approach to data access, e.g., instantiate and release your context after you're finished with it:
using (var context = new DataContext()) {
// Do work here.
}
And another quick one, its more efficient to using Any instead of Count as using Count causes the entire enumerable to be enumerated to get the result, where as Any will fall out at the first valid instance.

Categories

Resources