ObjectDisposedException when getting foreign key field - entity-framework

I created my model using Db Context Generator, using EF 4.
My model is like this:
Program Table:
ID
Name
Group Table:
ID
Name
ProgramID (Associated to Program.ID)
I want to display these columns in my grid:
Program.Name - Group.Name
But grdGroups.DataSource = db.Groups.ToList()
doesn't return Program.Name
When I try to this I get ObjectDisposedException.
Partial Public Class Group
Public ReadOnly Property ProgramName() As String
Get
Return Program.Name
End Get
End Property
End Class
What's the best way to return the Program.Name to include it in the grid datasource?

When I try to this I get
ObjectDisposedException
The problem is lazy loading - EF did not materialize the related Program entity, hence when you try to access Program.Name it will try and re-query the DB, but the context has been disposed at this point, so you get an exception.
You can use an Include() query when you retrieve your Group entity, to specify that you also want to load the related Program entity, i.e. :
var groups = context.Groups.Include(x => x.Program);

Related

Queue<T> type with Entity Framework Cast error

I have an entity A which holds a Queue<XYZ> B property. I want to persist it in a MySQL database. When migrating, the table is created correctly - each entity A has a table depicting Queue<XYZ> B. However, when I want to query the data from the database using:
A entityA = await _context.A.Include(entityA => entityA.B).FirstOrDefaultAsync((...));
Then I get such an error:
System.InvalidCastException: Unable to cast object of type 'System.Collections.Generic.Queue'1[API.Models.XYZ]' to type
'System.Collections.Generic.ICollection'1[API.Models.XYZ]'.
When I change the Queue<XYZ> B to List<XYZ> B then it works fine.
Is it impossible to automatically persist a queue to a database with Entity Framework?
Or do I have to do some extra work?
I have an entity A which holds a Queue B property. I want to
persist it in a MySQL database. When migrating, the table is created
correctly - each entity A has a table depicting Queue B. However,
when I want to query the data from the database using:
A entityA = await _context.A.Include(entityA => entityA.B).FirstOrDefaultAsync((...));
According to your description and the query statement, I have created a DeparmentViewModel with the Queue property, and reproduced the error when query the database using EF core.
public class DepartmentViewModel
{
[Key]
public int DepId { get; set; }
public string DepName { get; set; }
public Queue<EmployeeViewModel> EmployeeViewModels { get; set; }
}
To solve this issue, it seems that we could re-generate a Queue object based on the query result, like this:
DepartmentViewModel queryresult = _context.DepartmentViewModels
.Include(c=>c.EmployeeViewModels)
.Where(c => c.DepId==2) //
.Select(c=> new DepartmentViewModel()
{
DepId = c.DepId,
DepName = c.DepName,
EmployeeViewModels = new Queue<EmployeeViewModel>(c.EmployeeViewModels.ToList())
}).FirstOrDefault();
Besides, I also found that if using the Queue, when insert new data, it might cause the following error:
"System.InvalidOperationException: 'The type of navigation property 'EmployeeViewModels' on the entity type 'DepartmentViewModel' is 'Queue' which does not implement ICollection. Collection navigation properties must implement ICollection<> of the target type.'"
So, in my opinion, when you create Navigation Properties, try to use List<T> or ICollection<T>, instead of using Queue<T>.

Entity Framework refuses to save value on new column

I just changed our database, adding a new column to a table and setting it as a foreign key. We're using EF4 Database first, so I updated the model from the DB, added my new field to the DTOs and everything looked great until I tried to save data to it.
The new column is called DiaryEventId, and because it's a FK there's also a virtual property on the object called DiaryEvent. Here's what the code looks like:
public void SaveDocument(Guid CaseId, string diaryText, string ActivityType)
{
Guid eventTypeId = RepositoryHelper.GetDiaryEventFromCache("Document Uploaded", _commonQueryContext);
//this wanders off and created a diary event object, adds it to
//the context and returns its ID
Guid diaryId = RepositoryHelper.AuditEvent(CaseId, diaryText, commonUpdateContext);
Entities.DocumentMetadata docData = new Entities.DocumentMetadata()
{
Id = Guid.NewGuid();,
ActivityType = activityType,
DiaryEventId = diaryId
};
_commonUpdateContext.DocumentMetadatas.Add(docData);
_commonUpdateContext.SaveChanges();
}
This compiles and runs fine, and when you step through it it appears to function as expected - diaryId is generated and set on the object. But in the DB, it always appears as null.
I've tried calling SaveChanges after adding the diary event (to make sure the key has something to connect to) and I've tried adding the actual DiaryEvent object to the virtual property rather than just the ID - both have the same effect.
When I watch what's going on in SQL Profiler, I can see that the INSERT statement simply ignores my new column completely - it's not listed in the insert columns at all.
Really got no idea what's going on. Any ideas?
Try modifying the object after adding it to the context, just as a test.
_commonUpdateContext.DocumentMetadatas.Add(docData);
Entities.DocumentMetadata docData = new Entities.DocumentMetadata()
{
Id = Guid.NewGuid();,
ActivityType = activityType,
DiaryEventId = diaryId
};
_commonUpdateContext.SaveChanges();
Or is this perhaps a typo?
Entities.DocumentMetadata docData = new Entities.DocumentMetadata()
{
Id = Guid.NewGuid();, <-------------typo?
Beyond that, it will require a bit of info on how you have your entities mapped out. Is there a navigation property between DiaryEvent and DocumentMetadata? Is the key defined as nullable (I'm assuming it is)? Is ActivityType getting persisted correctly?

Navigation Key lost after trying to delete

I have code first entity framework.
when I'm trying to delete row from table that have foreign key to other table i get a exception. after handling the exception when I try load my data again the Navigation Key of selected item that i try to delete is become null
why this happen and how can i fix it.
the delete process is so simple :
public class Person
{
public int ID {get;set;}
public string Name {get;set;}
public Something Something {get;set;}
public ICollection<Profile> Profile {get;set;}
}
try
{
var p = en.Person.First(t => t.ID == 14);
//p.Something here is not null;
en.Remove(p)
en.SaveChanges(); // I'm get an exception here
}
catch { /*error handling */}
finally
{
var p = en.Person.First(t => t.ID == 14);
//but p.Something here is null;
}
but in en.SaveChange() i get an exception.
The DELETE statement conflicted with the FOREIGN KEY constraint
"FK_person_profile
this is a sample of my class.
that SomeThing Property is a Navigation Key.
in first select the Something have value.
but in second select inside finally block its become null.
after fixing the delete problem now I got the same problem after adding object to database.
and that reload function doesn't help.
any suggestion?
I think I understand your problem - you're deleting an entity, it's causing an error and you want to recover. However, in your finally block when you get your entity again from your current context again it's not correct.
The issue is that you're expecting your context to reload from the database, but that's not quite how it works. What you're actually doing is going back to your context, which is a unit of work and retrieving the entity in memory, because the entity your retrieving is flagged for deletion so it's properties are not being loaded. If you want to refresh from the database, you'll need to reload the entity fully using the Entry, using the DbEntityEntry.Reload.
Using your code an an example:
var p = en.Person.First(t => t.ID == 14);
en.Entry(p).Reload();

Accessing foreign key value (int) in Entity Framework

I just spent the last 3-4 hours trying to retrieve a foreign key value using linq to entities and a stored procedure. Any advice is much appreciated.
public JsonResult GetEvents(double? start, double? end)
{
AnoEntities _dbAno = new AnoEntities();
var events = _dbAno.Events_GetByDateRange(fromDate, toDate);
var eventList = from e in events
select new
{
id = e.id,
title = e.title,
className = e.event_types.type.ToString()
};
return Json(eventList.ToArray());
}
type_id is the foreign key value that i'm trying to reach. I can't get it so appear in the entity data model and I can't seem to get to it. e.event_types and e.event_typesReference are both null so things like e.event_typesReference.EntityKey.EntityKeyValues.First().Value.ToString() aren't working.
Thanks!
I don't see any .Include methods or Load methods on even_types and I'm assuming your returning IEnumerable from your _dbAno.Events_GetByDateRange(fromDate, toDate). Like Craig pointed out in the comments if your return type of GetByDateRange is IQueryable you'd be projecting and EF should eager load for you.
Just a reminder that implicit lazy loading isn't supported out of the box in Entity Framework 1.0. You'll need to manually load the event_types with Load() or use the Include method on ObjectQuery.

How to relate entities that are not directly mapped through a navigation property

I have an object that has been populated with the contents of four different related entities. However i have another entity in which i cannot include as part of the query due to it not being related in the navigation properites directly to the IQueryable table i am pulling. The entity i am trying to include is related to one of the four different entities that have been included successfully.
Is there a way to include(during db hit or afterwards) this entity as part of the overall object i am creating?
Here is an example of what my calls look like to build the CARTITEM object:
public List<CARTITEM> ListCartItem(Guid cartId)
{
//Create the Entity object
List<CARTITEM> itemInfo = null;
using (Entities webStoreContext = new Entities())
{
//Invoke the query
itemInfo = WebStoreDelegates.selectCartItems.Invoke(webStoreContext).ByCartID(cartId).ToList();
}
//Return the result set
return itemInfo;
}
here is the selectCartItems filter(Where i would normally do the includes):
public static Func<Entities, IQueryable<CARTITEM>> selectCartItems =
CompiledQuery.Compile<Entities, IQueryable<CARTITEM>>(
(cart) => from c in cart.CARTITEM.Include("ITEM").Include("SHIPPINGOPTION").Include("RELATEDITEM").Include("PROMOTION")
select c);
from this i have my CARTITEM object. Problem is i want to include the PROMOTIONTYPE table in this object, but since the CARTIEM entity doesn't have a navigation property directly to the PROMOTIONTYPE table i get an error.
Let me know if you need any more clarification.
Thanks,
Billy
You can use join and if it is the same database and server it should generate the join in SQL and do it all in one call...
LinqToEnties join example