1

The problem I am having is as follows, due to caching issues we are putting the following before the start of every ET query:

DataBase.Refresh(System.Data.Objects.RefreshMode.ClientWins, DataBase.PublicUsers);

However, this is causing pages to take ages to load as the above command makes two calls to the database.

Does anybody know away to stop EF from caching without having to put that command before every query?

swade1987
  • 1,553
  • 5
  • 19
  • 28
  • And why do you execute that refreshing? – Ladislav Mrnka Jul 04 '12 at 14:30
  • so each time we perform the query we are using the most upto date data. – swade1987 Jul 04 '12 at 14:35
  • What kind of application are you building? You mentioned pages - is it a web App? In such case this should never happen unless you are reusing context which makes your application useless anyway. – Ladislav Mrnka Jul 04 '12 at 14:41
  • We are developing a website, however my developers have said data seems to have cached before they used this method. Are you saying that if we alter data in the database manually we need to stop and start the application again? – swade1987 Jul 04 '12 at 14:43
  • No you don't need to start and stop application. This problem occurs only when you cache `DataBase` instance among multiple requests. And that is [something you should never do](http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392). – Ladislav Mrnka Jul 04 '12 at 14:52
  • so the best idea for implementing is using the "using" statements for each query? – swade1987 Jul 04 '12 at 15:09
  • It is usually enough to have single context instance per processed request. The command you showed is in such case used only for resolving concurrency issues. – Ladislav Mrnka Jul 04 '12 at 15:11
  • I am slightly confused so in the following query what would you do? http://pastebin.com/HH7iMQ2t – swade1987 Jul 04 '12 at 15:12
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13415/discussion-between-swade1987-and-ladislav-mrnka) – swade1987 Jul 04 '12 at 15:14
  • The website allows for the creation, editing and viewing of data – swade1987 Jul 04 '12 at 15:20

2 Answers2

2

To answer your initial question. If you don't want context to cache data you must execute query without change tracking.

Database.Hubs.MergeOption = MergeOption.NoTracking;
return DataBase.Hubs
            .Where(h =>
                h.BusinessId == null
                && h.TypeId != (int)HubType.BusinessPlace
                && h.ParentHubId != null
            );

But this will not solve your architecture issue related to static / shared context in a web app. You must change your architecture if you really want to create working application.

Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
0

You can set the MergeOption to all EntitieSet after create the context. Some like this:

var objSetProps = ctx.GetType().GetProperties().Where(prop => prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(ObjectSet<>));
foreach (PropertyInfo objSetProp in objSetProps)
{
    ObjectQuery objSet = (ObjectQuery)objSetProp.GetValue(ctx, BindingFlags.GetProperty, null, null, null);
    objSet.MergeOption = MergeOption.PreserveChanges;
}

Read about the MergeOption here: http://msdn.microsoft.com/en-us/library/system.data.objects.mergeoption.aspx Your will use NoTracking, I think.

But, iy you whant CLEAR the "cached" entities, detaching it.

var entidades = Ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged);
foreach (var objectStateEntry in entidades)
    Ctx.Detach(objectStateEntry.Entity);

Where Ctx are my Context.

Tiago Gouvêa
  • 10,575
  • 2
  • 60
  • 69