Print Page | Close Window

Cache ignored when a view closed and then opened

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=2236
Printed Date: 29-Jul-2026 at 6:11am


Topic: Cache ignored when a view closed and then opened
Posted By: alindzon
Subject: Cache ignored when a view closed and then opened
Date Posted: 19-Oct-2010 at 3:49am
I am trying to fully understand the cacheing.  If I completely load a file, all subsequent access seems to be through cache, which is great.  If I retrieve only a portion of the file, and page through it, again the cache works fine while the current UI is running.  But if I close and reopen the view, or open a second view onto the same data, the cache is not used.
 
I am curious what the default cacheing behaviours are, and if I can influence them to use cache when its available, even in those cirumstances.
 
This is one of the viewmodels involved

public class CustomersViewModel : ViewModelBase

{

public class MyDataContext

{

storeEntities _Context;

public storeEntities Context

{

get

{

if (_Context == null)

{

_Context = new storeEntities();

}

return _Context;

}

}

MyQueryableCollectionView _Data;

public MyQueryableCollectionView Data

{

get

{

if (_Data == null)

{

var collection = new RadObservableCollection<Customer>();

_Data = new MyQueryableCollectionView(collection);

_Data.PageSize = 10;

Refresh(true);

}

return _Data;

}

}

void Refresh(Boolean needsRefresh)

{

IdeaBlade.EntityModel.EntityScalarQueryOperation<int> countQuery;

if (needsRefresh)

{

countQuery = (from o in (EntityQuery<Customer>)Context.Customers.Where(_Data.FilterDescriptors) select o).AsScalarAsync().Count();

countQuery.Completed += (sender, args) =>

{

_Data.SetTotalItemsCount(args.Result);

};

}

var query = (EntityQuery<Customer>)Context.Customers.OrderBy(o => o.Company)

.Where(Data.FilterDescriptors)

.Sort(Data.SortDescriptors)

.Page(Data.PageIndex, Data.PageSize);

query.ExecuteAsync().Completed += (s, e) =>

{

var source = (RadObservableCollection<Customer>)_Data.SourceCollection;

source.SuspendNotifications();

source.Clear();

source.AddRange(e.Results);

source.ResumeNotifications();

_Data.CollectionChanged += CollectionChanged;

};

}

void CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)

{

_Data.CollectionChanged -= CollectionChanged;

Refresh((((Telerik.Windows.Data.QueryableCollectionView)(sender))).NeedsRefresh);

}

 

public class MyQueryableCollectionView : QueryableCollectionView

{

public MyQueryableCollectionView(IEnumerable source)

: base(source)

{ }

private int itemCount;

protected override IQueryable CreateView()

{

return IsGrouped ? QueryableSourceCollection.GroupBy(GroupDescriptors) : QueryableSourceCollection;

}

internal void SetTotalItemsCount(int count)

{

itemCount = count;

OnPropertyChanged(new PropertyChangedEventArgs("ItemCount"));

OnPropertyChanged(new PropertyChangedEventArgs("TotalItemCount"));

}

public override int TotalItemCount

{

get

{

return itemCount;

}

protected set

{

base.TotalItemCount = value;

}

}

public override int ItemCount

{

get

{

return itemCount;

}

}

}

}

}

}

 



Replies:
Posted By: sbelini
Date Posted: 22-Oct-2010 at 11:50am
alindzon,
 
Each EntityManager has its own entity cache and query cache.
 
When you execute a query, the query is stored in the entity manager's query cache and the result set in the entity cache.
 
If you execute a query and it's already in the query cache, the entity will recognize that and only look in the entity cache, otherwise it will look in the datasource.
 
You can find detailed information on entity cache at http://drc.ideablade.com/xwiki/bin/view/Documentation/EntityCaching_Intro - http://drc.ideablade.com/xwiki/bin/view/Documentation/EntityCaching_Intro  
and about the query cache at
http://drc.ideablade.com/xwiki/bin/view/Documentation/AdvPersist_Intro#HQueryCache - http://drc.ideablade.com/xwiki/bin/view/Documentation/AdvPersist_Intro#HQueryCache  and
http://drc.ideablade.com/xwiki/bin/view/Documentation/AdvPersist_Intro#HQueryCache - http://drc.ideablade.com/xwiki/bin/view/Documentation/AdvPersist_Intro#HQueryCache
 
When you reopen a view or open a second view, are they all working with the same instance of the entity manager?
Is the same query being re-executed, or are you executing a different query? 


Posted By: alindzon
Date Posted: 22-Oct-2010 at 12:01pm
Now this is getting interesting.  So if I want my application to retrieve data from the cache and to share the cache, I should create one instance of the entity manager when I start the application, and use it for each viewmodel, without creating new instances.
 
But if I want something to be completely independant, and to not be corrupted by the other viewmodels,  then I should create a new instance of the entity manager.  Does that make sense?
 


Posted By: smi-mark
Date Posted: 22-Oct-2010 at 12:18pm
One way is to create a new EntityManager for each view, you then import the cache from the master EntityManager.


Posted By: alindzon
Date Posted: 22-Oct-2010 at 12:21pm
Please show me how you would make the master entitymanager available to the views, and how you would import the cache.


Posted By: alindzon
Date Posted: 23-Oct-2010 at 8:55am
It looks like there are two options, a master entitymanager, or using one entitymanager for the entire application.  I am assuming from a memory perspective one entitymanager is better since then you will not have all those duplicate caches running around.
 
Tell me if this makes sense, and please show me how you would set it up, and then connect to it from each repository.  I am still new to C# and this object stuff, my main experience was long ago with C+, so I am still getting used to hooking things up.
 


Posted By: alindzon
Date Posted: 24-Oct-2010 at 8:42am
Based on your documentation I am not sure if this will work or not since it is still a new query.
 
So let me put the questions another way.
 
if you want to load specific tables completely once when a program starts up, and then to use those tables for something like includes for many views without accessing the database again, how would you do it.
 
Examples are
Manufacturer Names, referenced by ManufacturerID
Distributor Names, referenced by DistributorID
State Names and Tax Rates referenced by StateID
etc...
 
Right now when the application starts, these viewmodels are all executed successfuly and if those views are used, there is no database access.  But if that data is required for another view then the cache is ignored.
 
From a design perspective, it makes no sense to go to the database for data that has already been loaded in its entirety into cache.  So what is the optimal devforce way to take advantage of this data, to reduce the need to retrieve this data over and over again from the database?
 
Also how would one write the query so that it retrieves only the desired fields from the database for the view in question?  I undertstand there is a way with a lamda expression.
 
 


Posted By: WardBell
Date Posted: 24-Oct-2010 at 11:34pm
Alindzon
 
We cannot make sense of your claims. DevForce does not know about ViewModels. If you see one kind of behavior with one set of VMs and different behavior with a different set of VMs, it is most probable that the explanation is to be found in your VMs. I suspect that you are using multiple EntityManagers and have lost track of what they hold.
 
--
"how would one write the query so that it retrieves only the desired fields from the database for the view in question?"
You'll find examples of projection in the Cookbook http://drc.ideablade.com/xwiki/bin/view/Documentation/CookbookSimpleProjection - here and http://drc.ideablade.com/xwiki/bin/view/Documentation/ProjectIntoServerType - here .



Print Page | Close Window