Quantcast
Channel: Entity Framework
Viewing all articles
Browse latest Browse all 10318

Edited Issue: Add extension points to "load/query execute" (to allow custom entity caching and loading) [926]

$
0
0
__This is a specific scenario of the more general [Lifecycle Hooks feature](http://entityframework.codeplex.com/workitem/872).__

It would be very powerful to allow the EntityCollection and EntityReference class Load functions to be extensible. I've already done so in my copy of the EF source code, and I'll describe what I've done below. But first, the scenario:

In my application, I've implemented two custom caches. My "Entity cache" caches individual Entities. My "Query cache" caches IQueryable objects with their results. These caches are used by my Repository class, which is used exclusively as the DAL. So anything retrieved directly from my Repository uses this cache correctly. However, anything "lazy loaded", including both EntityCollections and EntityReferences, have their own internal way of fetching entities. This causes two problems:

1. Entities fetched internally by EntityCollection or EntityReference aren't put into my cache. This is because there's no good extension point where EF says "I just executed this IQueryable, and here's what I got back".
2. Entities fetched internally by EntityCollection or EntityReference can't "fetch" entities from my cache if they already exist. This is because there's no good extension point where EF says "I need some entities. Does anybody have another way I could get these entities? Otherwise, I'll have to execute this IQueryable."

I downloaded the EF source code and added this functionality pretty easily. I'm not claiming it's the perfect solution, but it works very well for me. Here are the code changes I made:

To the EntityCollection.cs class:

```
// Allow the load to be overridden.
// If this member is set, it is used instead of sourceQuery.Execute(...) in the Load method.
public Func<IQueryable<TEntity>, EntityCollection<TEntity>, IList<TEntity>> LoadOverride = null;
...
internal virtual void Load(List<IEntityWrapper> collection, MergeOption mergeOption) {
...
// Allowing the load to be overridden.
// Replace the following code:
// refreshedValues = sourceQuery.Execute(sourceQuery.MergeOption);
// With this code:
if (LoadOverride != null)
{
refreshedValues = LoadOverride(sourceQuery, this);
}
else
{
refreshedValues = sourceQuery.Execute(sourceQuery.MergeOption);
}
...
}

```
To the EntityReference`.cs class:

```
// Allow the load to be overridden.
// If this member is set, it is used instead of sourceQuery.Execute(...) in the Load method.
public Func<IQueryable<TEntity>, EntityReference<TEntity>, IEnumerable<TEntity>> LoadOverride = null;
...
public override void Load(MergeOption mergeOption) {
...
// Allowing the load to be overridden.
// Replace the following code:
// var objectResult = sourceQuery.Execute(sourceQuery.MergeOption);
// refreshedValue = objectResult.ToList();
// With this code:
if (LoadOverride != null)
{
var objectResult = LoadOverride(sourceQuery, this);
refreshedValue = objectResult.ToList();
}
else
{
var objectResult = sourceQuery.Execute(sourceQuery.MergeOption);
refreshedValue = objectResult.ToList();
}
...
}

```

I'm not using the Async methods yet, so I didn't modify those, but the idea is the same.

Conclusion? In about 20 lines of code, you can make EF much more powerful by providing an extension point for EntityCollection and EntityReference loading.

I would LOVE it if you could get this into a release as soon as possible. To me, it's the most important feature missing from EF.


Viewing all articles
Browse latest Browse all 10318

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>