Error with multiple open data readers for child entity - entity-framework-4

I have a ef 4 model and I'm using self tracking entities. In this model there is an entity called Organisation. Each Organisation can have many Locations (addresses). If I try to select a single location (so I can delete it), thus:
var location = _container.Locations.FirstOrDefault(l => l.Id == id);
I get an erorr that there is already a data reader open so I cant open another. If I do the following:
var location = _container.Locations.Include("Organisation").FirstOrDefault(l => l.Id == id);
Then it all works just fine.
Using Intellitrace I can see that with the failed query it executes an ADO command to get just the location then does another command to get the location and the organisation.
Is this a bug or something I need to do differently for selftracking entities?

No it is not a bug. This usually happens if you iterate result of one query and in this iteration you execute another query (it can also happen due to lazy loading but lazy loading is not supported with self tracked entities). The simplest solution is simply allowing multiple active data readers (your database must support it). In case of SQL Server 2005 and newer you can simply add to your connection string this part: MultipleActiveResultSets=true;

Related

DBContext (entity framework) and pre-loaded entities

I use code first in a web application where I have a form to upload text files and import the data into my database.
Each file may have up to 20.000+ records for import.
To speed things up I preload some entities so not to ask the DbContext every time. Then when I create an object for insert, I do for example:
myNewObject.Category = preloadedCategories.First(p => p.Code == code);
I have read some articles on the web because EF is extremey slow on batch inserts, so what I do is:
first use Configuration.AutoDetectChangesEnabled = false;
then every 1000 records I dispose the object and make a new one.
BUT! since the preloaded entities where loaded from a db context that was disposed, after making a new DbContext, I have a problem with preloadedCategories.First(p => p.Code == code). When I make a SaveChanges(), EF tries to also save the preloadedCategories.First(p => p.Code == code) object and fails.
So how can I achive this? I don't want to aks the DbContext every time to load some (non changing) objects. Is it possible?
thanks
When dealing with a large number of records in EF, a few things will help
As #janhartmann states, use .AsNoTracking()
As you stated, use Configuration.AutoDetectChangesEnabled = false, which will require the next point
Use context.Categories.Entry(category).State = EntityState.Modified to attach a disconnected entity to a context and mark is as modified
Also make check that preloadedCategories is no longer an IQuerable and that the data really is local and not trying to lazy load from the database.
If there are no changes to your Category object and you just want to link your myNewObject to an existing category, you have two options
Set the foreign key on myNewObject instead of the navigation property
Use context.Products.Entry(myNewObject).State = EntitySate.Added instead of context.Products.Add(myNewObject) to avoid it adding the entire graph of navigation properties
Good luck

Why is Entity framework loading data from the db when I set a property?

I have two tables (there are more in the database but only two are involved here).
Account and AccountStatus, an account can have an AccountStatus (active,inactive etc).
I create a new Account and set a couple of properties but when I reach this code:
1. var status = db.AccountStatuses.SingleOrDefault(s => s.ID == (long)AccountStatusEnum.Active);
2. account.AccountStatus = status;
3. db.Accounts.AddObject(account);
The first line executes fine, but when I reach the second line it takes a REALLY long time, and when I step in to the code it seems that every single account is loaded from the database.
I don't see why it should even want to load all the accounts?
We use Entity Framework 4 and Poco and we have lazy loading enabled.
Any suggestions?
Cheers
/Jimmy
You have to be careful which constructs you use to fetch data, as some will pull in the whole set and filter afterword. (aside: the long time delay may be the database being created and seeded, if there isn't one already, it will occur the first time you touch it, likely with a query of some sort. Also remember that when you retrieve a whole dataset, you may in actuality only have what amounts to a compiled query that won't be evaluated until you interact with it).
Try this form instead and see if you have the same issue:
var status = db.AccountStatuses.Where(s => s.ID == (long)AccountStatusEnum.Active);

EF4 - Self tracking entities and inheritance and eager loading

I know this has been asked before in several ways but none of the answers seem applicable to me - or correct - or current, so I'll try again.
I have a large model with several intstances of inherited entities. One example is a Timetable that contains a collection of TimetableEvents. There are several sub-types of TimetableEvent, such as an InterviewTimetableEvent, BreakTimetableEvent and an ExercisetimeTableEvent. ExerciseTimetableEvent has a relationship to an Exercise entity.
I need to use self-tracking entities as I'm using a WCF back end to serve up data to several WPF clients in a stateless fashion.
So, I need to eager load everything and I thought that self-tracking entities would automatically do this but it appears they dont.
So, to get a timetable I need to do something like this:
var tt = (from s in ESSDataContainer.Timetables
.Include("TimetableEvents")
where s.TimetableId == timetableid
select s).FirstOrDefault();
This will give me the TimetableEvents but not the Exercises that are related to the ExerciseTimetableEvents. Ive tried the following (and several other suggestions) without luck:
var tt = (from s in ESSDataContainer.Timetables
.Include("TimetableEvents")
.Include("ExerciseTimetableEvents.Exercise")
where s.TimetableId == timetableid
select s).FirstOrDefault();
Is there a solution to this?
If not I'll go back to normal context tracking and connect to the database from a local container rather than using WCF.
Cheers
It's a bit tricky, but possible:
var tt = (from s in ESSDataContainer.Timetables
where s.TimetableId == timetableid
select new
{
TimeTable = s,
Events = s.TimeTableEvents,
Exercise = s.TimeTableEvents.OfType<ExerciseTimetableEvents>()
.Select(ett => ett.Exercise)
}).Select(s => s.TimeTable)
.AsEnumerable()
.FirstOrDefault();
Clear as mud, but, hey: No magic strings! Also, it has the advantage that it actually works....
There is a Proposal for this issua at Microsoft Connect:. If you think this worthy you can vote for it.

Tables from 2 databases in one LINQ to SQL class

I want to include a table (Events) from another database in my LINQ to SQL class.
How should I format the Data Source of that table?
I have tried with IP.dbo.Events, IP.DatabaseName.dbo.Events and so on, but can not get it to work.
The reason for all this is to select Events that a Client have attended.
I have also tried to have the table in another LINQ to SQL class, but then it complains on the Data Context.
public static IQueryable<Event> ByClientID(this IQueryable<Event> events, int clientID)
{
events = from e in events
from c in new MyDataContext().ClientCourses
where e.EventID == c.CourseID &&
c.ClientID == clientID
select e;
return events;
}
You can only use tables that reside on the same physical SQL Server in two different instances. I did this once as someone had "cleverly" put an application's DB across two database instances.
There is a blog post on it here that may help.
Could you create a view that returns the data from the 2nd database and use this instead? (Not tried this so absolutely no idea if it'll work :)
Obviously this is no good if you need to be saving to the other database too..

MVC DataContext Ok to Share One Connection or Not

When is the "unit of work" no longer a "unit"? Which scenario is better on resources? THe first creates one connection wheras the second creates 4.
using (DataContext dc=new DataContext)
{
var orders= from o in dc.orders
select ( new Product { property a= from a in ..join... select x,
property b= from b in ..join... select y,
property c= from c in ..join... select z.}
)
}
OR
using (DataContext dc=new DataContext)
{
var orders= from o in dc.orders
select ( new Product { property a = GetPropertyA(),
property b = GetPropertyB(),
property c = GetPropertyC()}
)
}
When using LINQ if you add one entity to another and they use a different data context you are going to get an error. I would suggest keeping the same data context for each unit of work you are using. You can easily identify the unit of work you are processing by using the repository pattern to write your data access classes. If you're not clear on the repository pattern, check out this entry
Generally speaking the less round trips to your database the better. However, in high scale apps we often make our databases more and more 'dumb' so we end up not doing any joins so we don't tie up CPU and memory on the SQL database server. It really depends on which resources you find more scarce. If your SQL server has plenty of resources do the join there, otherwise pulling it back separately would be better. Have you looked at the results of this in the SQL profiler? Are you sure it's 4 connections, or just 4 separate calls?

Resources