Querying Cached Entities with FromCacheOnly
For data that is less frequently updated like customer details, regularly fetching it from the data source is costly. FromCacheOnly queries the entities present in the cache and does not approach the data source in any case. Essentially, if the entity does not exist in the cache, it will still not be fetched from the data source.
Note
This API only works when entities are stored separately, i.e., the caching option StoreAs is set to SeparateEntities.
Important
The entities must be indexed in the NCache Management Center before they are used with FromCacheOnly.
- The following example fetches the customer information from the cache if the Customer entity exists. If not, the result set returned will be empty.
Prerequisites
- Install the following NuGet packages in your client application:
- Enterprise: EntityFrameworkCore.NCache
- OpenSource: EntityFrameworkCore.NCache.OpenSource
- Include the following namespaces in your application:
- The cache must be running.
- Make sure that the data being added is serializable.
- For API details, refer to: CachingOptions, StoreAs, FromCacheOnly, FromCacheOnlyAsync.
using (var context = new NorthwindContext())
{
var resultSet = (from cust in context.Customers
where cust.CustomerId == someCustomerId
select cust).FromCacheOnly();
}
Considerations for FromCacheOnly
FromCacheOnly supports aggregate functions. However, these functions only cache the result and not the entities themselves. Hence, NCache provides the QueryDeferred method that defers the query so the entities in the cache get the result in response to a query. For more details on deferred APIs, please refer to the chapter Query Deferred APIs. FromCacheOnly supports the following functions:
Group ByOrder By AscendingOrder By DescendingSumMinMaxAverageCountContainsLike
Keep in mind the following considerations while using LINQ with FromCacheOnly:
Except for
Count, all aggregate functions must have integer values.Countneeds to be provided with an entity to count.A single LINQ expression for
FromCacheOnlycannot use more than one aggregate function.Projections in LINQ expressions can only be performed if a
GroupByoperator and an aggregate function are used forFromCacheOnly.Multiple projections are not supported. Only one attribute can be projected in a LINQ expression (that is carried forward).
using (var context = new NorthwindContext())
{
var result = context.Employees
.Select(e => e.EmployeeId) // Multiple projections have not been performed
.GroupBy(eid => eid) // eId was projected so GroupBy had to be used
.DeferredMin() // MIN provided with a numeric attribute
.FromCacheOnly();
}
GroupByis primarily used for aggregating functions (grouping the result of queries using columns) and can only be used if the projection is complete beforehand and an aggregate function is used.GroupByhas to be the last operator in the LINQ expression except ifOrderByis used. In such cases, theGroupByfunction can be shifted forward (afterOrderBy) or backward (beforeOrderBy).
using (var context = new NorthwindContext())
{
var result = context.Products
.Where(data => data.ProductName == "Tofu")
.GroupBy(data => new { data.ProductName})
.Select(group => new
{
_String = group.Key.ProductName,
Count = group.Count()
})
.FromCacheOnly();
}
OrderBy(both ascending and descending) can only be used in a LINQ expression forFromCacheOnlyifGroupByis used.More than one
GroupByandOrderByoperator cannot be used in a single LINQ expression forFromCacheOnly.Joins are not supported so the
Include()method will not work.For LINQ expressions containing the
DateTimeinstances, all nodes in a cache cluster must have the sameDateTimeformat set up. Otherwise, it will result in a format exception. This problem arises when theDateTime.NowandDateTime.Parse()methods are used in a multi-node cache cluster. To avoid it, synchronize theDateTimeformat on both machines. Moreover, useDateTime.ParseExact()overDateTime.Parse(), as theParseExact()API restricts the user from specifying a format forDateTime.The
Likeoperator in EF Core performs pattern matching within character strings. Usually, it is employed withWhereinSELECTstatements to filter rows based on specific patterns or substrings within a column's value. Additionally, it allows the use of wildcards to match one or more characters in a string:
using (var context = new NorthwindContext())
{
var result = context.Customers
.Where(c => EF.Functions.Like(c.CompanyName, "Alfreds Futterkiste"))
.FromCacheOnly()
.ToList();
}
- The
Containsoperator can be used similarly to theLikeoperator to employ pattern-based searches within a given criteria.
using (var context = new NorthwindContext())
{
var result = context.Customers
.Where(b => (b.CompanyName.Contains("Alfreds Futterkist")))
.FromCacheOnly()
}
- The
Containsoperator can also be used to search through a dictionary.
using (var context = new NorthwindContext())
{
var customerList = new List<string> { "CustomerId", "Alfreds Futterkiste" };
var result = context.Customers
.Where(b => customerList.Contains(b.CompanyName))
.FromCacheOnly();
}
Implementing Asynchronous LINQ APIs
The asynchronous APIs have the same functionality as their synchronous counterparts, but with asynchronous behavior. The parameters passed to these methods are also the same.
FromCacheOnlyAsync
The following example fetches the customer information only from the cache if the Customer entity exists. If not, the result set returned will be empty, as the database is ignored.
using (var context = new NorthwindContext())
{
var options = new CachingOptions
{
StoreAs = StoreAs.SeparateEntities
};
var task = (from cust in context.Customers
where cust.CustomerId == someCustomerId
select cust).FromCacheOnlyAsync();
task.Wait();
var resultSet = task.Result.ToList();
}
See Also
.NET: Alachisoft.NCache.EntityFrameworkCore namespace.
.NET: Alachisoft.NCache.Runtime.Caching namespace.