MetaGuru
MetaGuru

Reputation: 43853

How can I keep an object that was returned from an already disposed of DataContext?

Get User Action

[HttpGet]
[ActionName("Index")]
public ActionResult Get(int id)
{
    User u = UserCore.GetUser(id);

    if (u == null)
        return Content("user not found", "text/plain");

    return new XmlResult(u);
}

UserCore.GetUser

public static User GetUser(int UserID)
{
    using (PanamaDataContext db = new PanamaDataContext())
    {
        return (from u in db.Users where u.UserID == UserID select u).FirstOrDefault();
    }
}

The Route

routes.MapRoute(
    "GetUser",
    "user/{id}",
    new { controller = "Users", action = "Index" }
);

And finally the test URLs

/user/9000 returns "user not found" as expected (does not exist currently)

/user/75 (actually exists in the DB) however returns:

Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.'.

[ObjectDisposedException: Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.'.]
System.Data.Linq.DataContext.GetTable(Type type) +1020550
System.Data.Linq.CommonDataServices.GetDataMemberQuery(MetaDataMember member, Expression[] keyValues) +120
System.Data.Linq.DeferredSourceFactory1.ExecuteKeyQuery(Object[] keyValues) +258
System.Data.Linq.DeferredSourceFactory
1.Execute(Object instance) +928 System.Data.Linq.DeferredSource.GetEnumerator() +53
System.Data.Linq.EntitySet1.Load() +112
System.Data.Linq.EntitySet
1.get_Count() +9
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterUser.Write14_User(String n, String ns, User o, Boolean isNullable, Boolean needType) +5060
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterUser.Write15_User(Object o) +144

[InvalidOperationException: There was an error generating the XML document.]
System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id) +646
System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o, XmlSerializerNamespaces namespaces) +72
System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o) +10 ...

I'm assuming this is because the referenced object no longer exists but what can I do? Somehow copy the object that is returned from the DataContext?

Either way it should be returning XML and not that error.

Upvotes: 0

Views: 560

Answers (2)

SLaks
SLaks

Reputation: 887547

You need to eagerly include the child rows using the Include() method.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038940

You should use view models. Basically you should construct a view model inside the lifetime of the DataContext and pass this view model to the view result (in your case the XmlResult). This view model should be constructed by mapping properties of the actual domain model returned by your datacontext and all this should happen inside this context lifetime. Ayende Rahien has a great series of blog posts about view models (It's for NHibernate but the problem of disposed context is exactly the same as with EF data datacontexts).

Upvotes: 1

Related Questions