![]() |
VOOZH | about |
dotnet add package MACRIM.Core --version 6.8.1
NuGet\Install-Package MACRIM.Core -Version 6.8.1
<PackageReference Include="MACRIM.Core" Version="6.8.1" />
<PackageVersion Include="MACRIM.Core" Version="6.8.1" />Directory.Packages.props
<PackageReference Include="MACRIM.Core" />Project file
paket add MACRIM.Core --version 6.8.1
#r "nuget: MACRIM.Core, 6.8.1"
#:package MACRIM.Core@6.8.1
#addin nuget:?package=MACRIM.Core&version=6.8.1Install as a Cake Addin
#tool nuget:?package=MACRIM.Core&version=6.8.1Install as a Cake Tool
The MACRIM.Caching project extends the MACRIM framework’s caching capabilities to support table-based caching in Redis, replacing the in-memory LookupService with a scalable, persistent solution. It caches IEntity instances for SQL tables (or other data sources), enabling fast lookups for batch processing (5-10K rows) with dynamic indexing and segmented caching. The rebuilt RedisService addresses compile errors from the original CacheService<T>, integrating with IConfigService for configuration-driven caching.
Phase 1 implements caching in Redis, focusing on:
IEntity instances as Redis Hashes (segment:cacheName:segment:catalog) with TTL from expires.jsondata via keypattern expressions (e.g., {catalog},{name},{catalog}:{name}) using Redis Sets (segment:cacheName:index:value).IRepositoryBypass.SearchAsync, using LoadJSON for IEntity creation. Synchronized to ensure only one load per cache, with concurrent requests waiting.IEntity instances (SQL sync deferred to Phase 2).IConfigService (_configs[segment]["commands"]["caching"][cacheName]) for table, profile, keypattern, expires, segment.keypattern index entry (e.g., svc123) using GetRecord/GetRecordAsync, with expressions evaluated via ApplyLookups.To perform a lookup like {?:all-services(svc123,(catalog))} (retrieve a service by svc123 and return its catalog):
Configure Cache:
<command name="all-services" table="services" profile="sql" expires="600" segment="true" keypattern="{catalog},{name},{servicename},{catalog}:{name}">
<methods>
<method name="retrieve" type="MACRIM.Data.Extensions.Base.Search">
<parameters>
<parameter name="model" value="services" />
<parameter name="profile" value="sql" />
<parameter name="segment" value="{var:tenant}" />
</parameters>
</method>
</methods>
Set Up DI:
services.AddSingleton<ITableCachingService, RedisService>();
Update ApplyLookups (as static extension method):
case "lookup":
case "?":
var cacheSvc = me.Context.Services.GetRequiredService<ITableCachingService>();
if (cacheSvc == null) break;
var argStart = what.IndexOf('(');
var instruct = argStart > -1 ? what.Substring(++argStart) : string.Empty;
instruct = instruct.Length > 0 ? instruct.Remove(instruct.Length - 1) : string.Empty;
what = argStart > -1 ? what.Substring(0, argStart - 1) : what;
if (what == ".")
{
var pstart = instruct.IndexOf(',');
var lkey = instruct.Split(',').FirstOrDefault();
var lexp = pstart > -1 ? instruct.Substring(++pstart) : string.Empty;
if (lkey.StartsWith('(')) lkey = (string)me.ApplyLookups(lkey.Replace('(', '{').Replace(')', '}'), returnType, subReturnType, command, defaults);
var el = me.LookupCache.ContainsKey(lkey) ? me.LookupCache[lkey] : me.Spawn();
if (el != null && el.Found)
{
oFound = el.ApplyLookups(lexp.Replace('(', '{').Replace(')', '}'), returnType, subReturnType, command, defaults);
}
}
else
{
var pstart = instruct.IndexOf(',');
var lkey = instruct.Split(',').FirstOrDefault();
var lexp = pstart > -1 ? instruct.Substring(++pstart) : string.Empty;
if (string.IsNullOrEmpty(lkey) || string.IsNullOrEmpty(lexp))
{
oFound = string.Empty;
break;
}
var keyvalue = me.Attributes.GetValueOrDefault(lkey, "");
if (lkey.StartsWith('(')) keyvalue = (string)me.ApplyLookups(lkey.Replace('(', '{').Replace(')', '}'), returnType, subReturnType, command, defaults);
if (string.IsNullOrEmpty(keyvalue))
{
oFound = string.Empty;
break;
}
var record = cacheSvc.GetRecord(
keyvalue: keyvalue,
cacheName: what,
segment: me.Context?.Segment ?? "default"
);
if (record != null && record.Found)
{
oFound = record.ApplyLookups(lexp.Replace('(', '{').Replace(')', '}'), returnType, subReturnType, command, defaults);
}
else
{
oFound = string.Empty;
}
}
break;
Test Lookup:
{?:all-services(svc123,(catalog))} with me.Attributes["servicename"] = "svc123".oFound = "cat1" (from record.ApplyLookups("{catalog}", ...)).{?:all-services(svc123,(user:{id}:name:upper))} → oFound = "JOHN".Phase 2 will implement async SQL sync using Redis Lists, leveraging StartWatchingList, Polly retries, and a poison queue.
MACRIM.Core.Abstractions):
ITableCachingService: LoadCacheAsync, GetRecordAsync, GetRecord, UpsertRecordAsync (version: a37df99a-233d-424d-9c2d-fd5b56875548).IQueueService, QueueTask (Phase 2).MACRIM.Caching):
ICachingService and ITableCachingService (version: b9f8c7b5-4d2e-4f9b-9e2c-6f7a8b9c0f4e).ConnectionHelper for Redis.IRepositoryBypass via IContextService.Services.IEntity with attributes (table, profile, keypattern, expires, segment).Attributes["segment"], partition key.Attributes["catalog"], typically Key.Attributes (e.g., {"segment": "seg1", "catalog": "cat1", "name": "John", "age": "30"}).Attributes["catalog"].contacts).keypattern expressions (e.g., Index["cat1"], Index["cat1:John"]).RedisService.cs rebuilt for caching, supporting lookups by any keypattern index entry using keyvalue (e.g., svc123).profile parameter, deriving it from configuration.ITransaction.ExecuteAsync).GetRecord for ApplyLookups, optimized for high-frequency calls without logging.LoadCacheAsync to ensure one load per cache, with concurrent requests waiting.Test Phase 1:
RedisService with sample data (e.g., contacts, keypattern="{catalog},{name},{ssn},{catalog}:{name}").{?:cacheName(keyvalue,(expression))} in ApplyLookups (e.g., {?:all-services(svc123,(catalog))}).Sync Enhancements:
sync_version checks are needed for Phase 1 to detect table changes within TTL.DI Confirmation:
Microsoft.Extensions.DependencyInjection and singleton lifetime.T Handling:
BaseEntityConvertible for IRepository<T>, or specify models (e.g., Documents).Configuration:
IEntity output for _configs[segment]["commands"]["caching"][cacheName].Phase 2:
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 5 NuGet packages that depend on MACRIM.Core:
| Package | Downloads |
|---|---|
|
MACRIM.Extensions
Package of IEntity extensions for MSSQL, Azure, PDF and more |
|
|
MACRIM.Encryption
Default encryption provider used in MACRIM.net |
|
|
MACRIM.Models
Support for Documents, Events, and Reports |
|
|
MACRIM.Web
Controllers, services and middleware supporting MACRIM.net web applications |
|
|
MACRIM.Transfers
IEntity Extensions related to file transfer technologies |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 6.11.15-beta.2 | 222 | 11/14/2025 |
| 6.11.15-beta.1 | 276 | 11/12/2025 |
| 6.8.1 | 520 | 7/31/2025 |
| 6.6.15 | 573 | 6/15/2025 |
| 6.6.15-alpha.2 | 343 | 6/12/2025 |
| 6.5.15 | 391 | 5/24/2025 |
| 5.5.1 | 469 | 6/13/2024 |
| 4.12.15 | 918 | 12/15/2023 |
| 4.11.1 | 649 | 11/2/2023 |
| 4.10.15 | 685 | 10/20/2023 |