diff --git a/playground/dotnetcore/BasicCacheOperations/Code/BasicCacheOperations.csproj b/playground/dotnetcore/BasicCacheOperations/Code/BasicCacheOperations.csproj
new file mode 100644
index 0000000..b5d78fd
--- /dev/null
+++ b/playground/dotnetcore/BasicCacheOperations/Code/BasicCacheOperations.csproj
@@ -0,0 +1,28 @@
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
diff --git a/playground/dotnetcore/BasicCacheOperations/Code/Program.cs b/playground/dotnetcore/BasicCacheOperations/Code/Program.cs
new file mode 100644
index 0000000..dea1e67
--- /dev/null
+++ b/playground/dotnetcore/BasicCacheOperations/Code/Program.cs
@@ -0,0 +1,75 @@
+using Alachisoft.NCache.Client;
+using Alachisoft.NCache.Runtime.Caching;
+
+namespace NCache.Playground.Samples.BasicCacheOperations
+{
+ // Basic caching operations (CRUD) as an intro to NCache API
+
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Sample showing basic caching operations (CRUD) in NCache, along with expiration.\n");
+
+ string cacheName = args[0];
+
+ Console.WriteLine($"Connecting to cache: {cacheName}\n");
+ // Connect to the cache and return a cache handle
+ var cache = CacheManager.GetCache(cacheName);
+ Console.WriteLine($"Connected to Cache successfully: {cacheName}\n");
+
+ // Add product 10001 to the cache with a 5-min expiration
+ Product prod1 = new Product { ProductID = 10001, Name = "Laptop", Price = 1000, Category = "Electronics" };
+
+ string prod1Key = prod1.ProductID.ToString();
+ var productCacheItem = new CacheItem(prod1);
+ productCacheItem.Expiration = new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5));
+
+ // Add to the cache with 5min absolute expiration (TTL). Item expires automatically
+ cache.Add(prod1Key, productCacheItem);
+
+ Console.WriteLine("Product 10001 added successfully (5min expiration):");
+ PrintProductDetails(prod1);
+
+ // Get from the cache. If not found, a null is returned
+ Product retrievedprod1 = cache.Get(prod1Key);
+ if (retrievedprod1 != null)
+ {
+ Console.WriteLine("Product 10001 retrieved successfully:");
+ PrintProductDetails(retrievedprod1);
+ }
+
+ retrievedprod1.Price = 3000;
+
+ // Update product in the cache. If not found, it is added
+ productCacheItem = new CacheItem(retrievedprod1);
+ productCacheItem.Expiration = new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5));
+ cache.Insert(prod1Key, productCacheItem);
+
+ Console.WriteLine("Price for Product 10001 updated successfully:");
+ PrintProductDetails(retrievedprod1);
+
+ // Remove the item from the cache
+ cache.Remove(prod1Key);
+ Console.WriteLine($"Deleted the product {prod1Key} from the cache...\n");
+
+ Console.WriteLine("Sample completed successfully.");
+ }
+
+ private static void PrintProductDetails(Product product)
+ {
+ Console.WriteLine("ProductID, Name, Price, Category");
+ Console.WriteLine($"- {product.ProductID}, {product.Name}, {product.Price}, {product.Category} \n");
+ }
+ }
+
+ // Sample class for Product
+ [Serializable]
+ public class Product
+ {
+ public int ProductID { get; set; }
+ public string Name { get; set; }
+ public decimal Price { get; set; }
+ public string Category { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/BasicCacheOperations/Code/Properties/launchSettings.json b/playground/dotnetcore/BasicCacheOperations/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..caf17bf
--- /dev/null
+++ b/playground/dotnetcore/BasicCacheOperations/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "BasicCacheOperations": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/CacheItemLocking/Code/CacheItemLocking.csproj b/playground/dotnetcore/CacheItemLocking/Code/CacheItemLocking.csproj
new file mode 100644
index 0000000..3c2c35f
--- /dev/null
+++ b/playground/dotnetcore/CacheItemLocking/Code/CacheItemLocking.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
diff --git a/playground/dotnetcore/CacheItemLocking/Code/Program.cs b/playground/dotnetcore/CacheItemLocking/Code/Program.cs
new file mode 100644
index 0000000..cb13975
--- /dev/null
+++ b/playground/dotnetcore/CacheItemLocking/Code/Program.cs
@@ -0,0 +1,72 @@
+using Alachisoft.NCache.Client;
+
+namespace NCache.Playground.Samples.CacheItemLocking
+{
+ // Locking an item prevents other users from accessing it while you update it.
+ // You can lock with cache.GetCacheItem() or cache.Lock() and unlock with cache.Insert() or cache.Unlock()
+ // NOTE: Locking API is for application level locking. NCache already has its own internal locking
+ // for concurrency and thread-safe operations.
+
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Sample showing item level lock and unlock in NCache.\n");
+ string cacheName = args[0];
+
+ Console.WriteLine($"Connecting to cache: {cacheName}\n");
+ // Connect to the cache and return a cache handle
+ var cache = CacheManager.GetCache(cacheName);
+ Console.WriteLine($"Connected to Cache successfully: {cacheName}\n");
+
+ Product prod1 = new Product { ProductID = 11001, Name = "Laptop", Price = 1000, Category = "Electronics" };
+
+ string prod1Key = prod1.ProductID.ToString();
+ Console.WriteLine("Adding product 11001 to the cache...");
+
+ // add a product to the cache. if it already exists, the operation will fail
+ cache.Insert(prod1Key, prod1);
+ Console.WriteLine("Product added successfully:");
+ PrintProductDetails(prod1);
+
+ // Get product 11001 and lock it in the cache
+ Console.WriteLine("Get and lock product 11001 in the cache...");
+ LockHandle lockHandle = null;
+
+ // Passing "acquireLock:" flag also locks the item and "lockTimeout:" releases the lock after 10sec
+ var lockedCacheItem = cache.GetCacheItem(prod1Key, acquireLock: true, lockTimeout: TimeSpan.FromSeconds(10), ref lockHandle);
+ if (lockedCacheItem != null)
+ {
+ Console.WriteLine("Product 11001 retrieved and locked successfully:");
+ var retrievedProduct = lockedCacheItem.GetValue();
+ PrintProductDetails(retrievedProduct);
+
+ // Change the price of product 11001
+ retrievedProduct.Price = 2000;
+
+ // Insert() updates the item and releases the lock
+ cache.Insert(prod1Key, lockedCacheItem, lockHandle, releaseLock: true);
+ Console.WriteLine("Updated price of product 11001 and released the lock simultaneously in the cache...");
+
+ PrintProductDetails(retrievedProduct);
+ }
+ Console.WriteLine("Sample completed successfully.");
+ }
+
+ private static void PrintProductDetails(Product product)
+ {
+ Console.WriteLine("ProductID, Name, Price, Category");
+ Console.WriteLine($"- {product.ProductID}, {product.Name}, {product.Price}, {product.Category} \n");
+ }
+ }
+
+ // Sample class for Product
+ [Serializable]
+ public class Product
+ {
+ public int ProductID { get; set; }
+ public string Name { get; set; }
+ public decimal Price { get; set; }
+ public string Category { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/CacheItemLocking/Code/Properties/launchSettings.json b/playground/dotnetcore/CacheItemLocking/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..1375199
--- /dev/null
+++ b/playground/dotnetcore/CacheItemLocking/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "CacheItemLocking": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/DataStructures/Code/DataStructures.csproj b/playground/dotnetcore/DataStructures/Code/DataStructures.csproj
new file mode 100644
index 0000000..3c2c35f
--- /dev/null
+++ b/playground/dotnetcore/DataStructures/Code/DataStructures.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
diff --git a/playground/dotnetcore/DataStructures/Code/Program.cs b/playground/dotnetcore/DataStructures/Code/Program.cs
new file mode 100644
index 0000000..53cfd70
--- /dev/null
+++ b/playground/dotnetcore/DataStructures/Code/Program.cs
@@ -0,0 +1,129 @@
+using Alachisoft.NCache.Client;
+using Alachisoft.NCache.Client.DataTypes.Collections;
+
+namespace NCache.Playground.Samples.DataStructures
+{
+ // Use NCache distributed data structures (List and Queue in this sample). NCache provides
+ // Set, Dictionary, and Counter data structures as well. These data structures are distributed in the cluster
+ // for scalability and accessible to all clients.
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Sample showing distributed data structures in NCache (List, Queue) for more powerful data management.\n");
+
+ var cacheName = args[0];
+
+ Console.WriteLine($"Connecting to cache: {cacheName}\n");
+ // Connect to the cache and return a cache handle
+ var cache = CacheManager.GetCache(cacheName);
+ Console.WriteLine($"Connected to Cache successfully: {cacheName}\n");
+
+ Console.WriteLine("Create a List data structure and add products 'Electronics' to it...");
+
+ // Get the list if it already exists in the cache
+ IDistributedList productList = cache.DataTypeManager.GetList("productList");
+
+ if (productList == null)
+ {
+ // Create a List data structure in the cache and then add products to it
+ productList = cache.DataTypeManager.CreateList("productList");
+ }
+
+ // These products are directly added to the cache inside the List data structure when you add them below
+ productList.Add(new Product { ProductID = 15001, Name = "Laptop", Price = 2000, Category = "Electronics" });
+ productList.Add(new Product { ProductID = 15002, Name = "Kindle", Price = 1000, Category = "Electronics" });
+ productList.Add(new Product { ProductID = 15004, Name = "Smart Phone", Price = 1000, Category = "Electronics" });
+ productList.Add(new Product { ProductID = 15005, Name = "Mobile Phone", Price = 200, Category = "Electronics" });
+
+ PrintProductList(productList);
+
+ Console.WriteLine("Create a Queue data structure and add orders to it...");
+
+ // Get the queue if it already exists in the cache
+ IDistributedQueue orderQueue = cache.DataTypeManager.GetQueue("orderQueue");
+
+ if (orderQueue == null)
+ {
+ // Create a Queue data structure and then add orders to it by maintaining their sequence
+ orderQueue = cache.DataTypeManager.CreateQueue("orderQueue");
+ }
+
+ // These orders are directly added to the cache inside the Queue data structure when you enqueue them below
+ orderQueue.Enqueue(new Order { OrderID = 16248, Customer = "Vins et alcools Chevalier", OrderDate = new DateTime(1997, 7, 4), ShipVia = "Federal Shipping" });
+ orderQueue.Enqueue(new Order { OrderID = 16249, Customer = "Toms Spezialitäten", OrderDate = new DateTime(1997, 7, 5), ShipVia = "Speedy Express" });
+ orderQueue.Enqueue(new Order { OrderID = 16250, Customer = "Hanari Carnes", OrderDate = new DateTime(1997, 7, 7), ShipVia = "United Package" });
+ orderQueue.Enqueue(new Order { OrderID = 16251, Customer = "Victuailles en stock", OrderDate = new DateTime(1997, 7, 8), ShipVia = "Speedy Express" });
+
+ PrintOrderQueue(orderQueue);
+
+ Console.WriteLine("Fetch the list and print all items from the List data structure...");
+
+ // Fetch the List data structure from the cache and then access all items in it
+ var fetchedProductList = cache.DataTypeManager.GetList("productList");
+
+ PrintProductList(fetchedProductList);
+
+ Console.WriteLine("Process all orders from the Queue one by one in a sequence\n");
+
+ // Fetch the Queue data structure from the cache and then process all orders one by one in a sequence
+ var fetchedOrderQueue = cache.DataTypeManager.GetQueue("orderQueue");
+ while (fetchedOrderQueue.Count > 0)
+ {
+ var order = orderQueue.Dequeue();
+ Console.WriteLine("Process order : " + order.OrderID);
+ PrintOrder(order);
+ }
+
+ // Removing all items from the list
+ productList.RemoveRange(0, productList.Count);
+
+ Console.WriteLine("Removed products from the List data structure.\n");
+
+ Console.WriteLine("Sample completed successfully.");
+ }
+
+ static void PrintProductList(IList productList)
+ {
+ Console.WriteLine("ProductID, Name, Price, Category, Tags");
+ foreach (var product in productList)
+ {
+ Console.WriteLine($"- {product.ProductID}, {product.Name}, ${product.Price}, {product.Category}");
+ }
+ Console.WriteLine();
+ }
+
+ static void PrintOrderQueue(IDistributedQueue orderQueue)
+ {
+ Console.WriteLine("OrderID, Customer, Order Date, Ship Via");
+ foreach (var order in orderQueue)
+ {
+ Console.WriteLine($"- {order.OrderID}, {order.Customer}, {order.OrderDate.ToShortDateString()}, {order.ShipVia}");
+ }
+ Console.WriteLine();
+ }
+
+ static void PrintOrder(Order order)
+ {
+ Console.WriteLine("OrderID, Customer, Order Date, Ship Via");
+ Console.WriteLine($"- {order.OrderID}, {order.Customer}, {order.OrderDate.ToShortDateString()}, {order.ShipVia} \n");
+ }
+ }
+
+ class Product
+ {
+ public int ProductID { get; set; }
+ public string Name { get; set; }
+ public decimal Price { get; set; }
+ public string Category { get; set; }
+ }
+
+ class Order
+ {
+ public int OrderID { get; set; }
+ public string Customer { get; set; }
+ public DateTime OrderDate { get; set; }
+ public string ShipVia { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/DataStructures/Code/Properties/launchSettings.json b/playground/dotnetcore/DataStructures/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..afa6463
--- /dev/null
+++ b/playground/dotnetcore/DataStructures/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "DataStructures": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/EFCoreLinqCacheLookup/Code/EfCoreLinqCacheLookup.csproj b/playground/dotnetcore/EFCoreLinqCacheLookup/Code/EfCoreLinqCacheLookup.csproj
new file mode 100644
index 0000000..38e4829
--- /dev/null
+++ b/playground/dotnetcore/EFCoreLinqCacheLookup/Code/EfCoreLinqCacheLookup.csproj
@@ -0,0 +1,31 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
diff --git a/playground/dotnetcore/EFCoreLinqCacheLookup/Code/Program.cs b/playground/dotnetcore/EFCoreLinqCacheLookup/Code/Program.cs
new file mode 100644
index 0000000..e32dce7
--- /dev/null
+++ b/playground/dotnetcore/EFCoreLinqCacheLookup/Code/Program.cs
@@ -0,0 +1,119 @@
+using Alachisoft.NCache.EntityFrameworkCore;
+using Alachisoft.NCache.Runtime.Caching;
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
+
+namespace NCache.Playground.Samples.EFCoreCacheLookup
+{
+ // Use NCache integration with EF Core (thru Extension Methods) to load reference data into the cache
+ // and later search the cache thru EF Core LINQ queries. This is not resultset caching.
+ // We're using an SQLite in-memory database (with "Code First" approach) that goes away when the process ends.
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Sample showing NCache EF Core Extension Methods to load data in the cache and then use LINQ to query for it.\n");
+
+ using (var dbContext = new ProductsDbContext(args[0]))
+ {
+ dbContext.Database.EnsureCreated();
+
+ Console.WriteLine("LoadIntoCache: Adding all products to the cache thru EF Core Extension Method...");
+
+ // Cache each object separately
+ var cachingOptions = new CachingOptions() { StoreAs = StoreAs.SeperateEntities };
+
+ // This method should use LINQ to load all products. Currently, it is using EF Core mapping to the Product table
+ // We need to show how to use LINQ here even though all products will be loaded
+ // p => true is a simple expression that returns true for every element in the collection.
+ var products = dbContext.Products.Where(p => true).LoadIntoCache(cachingOptions).ToList();
+
+ PrintProducts(products);
+
+ Console.WriteLine("Find products with Category IN (\"Electronics\", \"Stationery\") AND price < $2000");
+
+ // Creating an array of categories for filtering products
+ var categoryFilter = new[] { "Electronics", "Stationery" };
+
+ var fetchedProducts = dbContext.Products
+ .Where(p => categoryFilter.Contains(p.Category) && p.Price < 2000)
+ .FromCacheOnly()
+ .ToList();
+
+ PrintProducts(fetchedProducts);
+
+ Console.WriteLine("Find all \"phone\" products (using LIKE operator) AND (Category = \"Electronics\" OR Category = \"Stationery\")");
+ var keyword = "Phone";
+ fetchedProducts = dbContext.Products
+ .Where(p => p.Name.Contains(keyword) && (p.Category == "Electronics" || p.Category == "Stationery"))
+ .FromCacheOnly()
+ .ToList();
+
+ PrintProducts(fetchedProducts);
+
+ Console.WriteLine("Sample completed successfully.");
+ }
+ }
+
+ static void PrintProducts(List products)
+ {
+ Console.WriteLine("ProductID, Name, Price, Category");
+ foreach (var product in products)
+ {
+ Console.WriteLine($"- {product.ProductID}, {product.Name}, ${product.Price}, {product.Category}");
+ }
+
+ Console.WriteLine();
+ }
+ }
+
+ public class ProductsDbContext : DbContext
+ {
+ public string _cacheName;
+ public DbSet Products { get; set; }
+
+ public ProductsDbContext(string cacheName)
+ {
+ _cacheName = cacheName;
+ }
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ string cacheId = _cacheName;
+
+ Console.WriteLine($"Connecting to cache: {cacheId}\n");
+ NCacheConfiguration.Configure(cacheId, DependencyType.Other);
+ Console.WriteLine($"Connected to Cache successfully: {cacheId}\n");
+
+ // Configure in-memory database using SQLite provider
+ var connection = new SqliteConnection("Data Source=:memory:");
+ connection.Open();
+ optionsBuilder.UseSqlite(connection);
+
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.Entity().HasData(
+ new Product { ProductID = 14001, Name = "Laptop", Price = 2000, Category = "Electronics" },
+ new Product { ProductID = 14002, Name = "Kindle", Price = 1000, Category = "Electronics" },
+ new Product { ProductID = 14003, Name = "Book", Price = 100, Category = "Stationery" },
+ new Product { ProductID = 14004, Name = "Smart Phone", Price = 1000, Category = "Electronics" },
+ new Product { ProductID = 14005, Name = "Mobile Phone", Price = 200, Category = "Electronics" }
+ );
+ }
+ }
+
+ [Serializable]
+ public class Product
+ {
+ public int ProductID { get; set; }
+
+ [QueryIndexed]
+ public string Name { get; set; }
+ [QueryIndexed]
+ public int Price { get; set; }
+ [QueryIndexed]
+ public string Category { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/EFCoreLinqCacheLookup/Code/Properties/launchSettings.json b/playground/dotnetcore/EFCoreLinqCacheLookup/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..50a379a
--- /dev/null
+++ b/playground/dotnetcore/EFCoreLinqCacheLookup/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "EfCoreLinqCacheLookup": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/EFCoreResultsetCaching/Code/EfCoreResultsetCaching.csproj b/playground/dotnetcore/EFCoreResultsetCaching/Code/EfCoreResultsetCaching.csproj
new file mode 100644
index 0000000..5258d49
--- /dev/null
+++ b/playground/dotnetcore/EFCoreResultsetCaching/Code/EfCoreResultsetCaching.csproj
@@ -0,0 +1,33 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
diff --git a/playground/dotnetcore/EFCoreResultsetCaching/Code/Program.cs b/playground/dotnetcore/EFCoreResultsetCaching/Code/Program.cs
new file mode 100644
index 0000000..4e67389
--- /dev/null
+++ b/playground/dotnetcore/EFCoreResultsetCaching/Code/Program.cs
@@ -0,0 +1,106 @@
+using Alachisoft.NCache.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Data.Sqlite;
+
+namespace NCache.Playground.Samples.EFCoreResultsetCaching
+{
+ // Use NCache integration with EF Core (thru Extension Methods) to seamlessly cache EF Core query resultset.
+ // Next time, EF Core fetches the resultset from the cache and saves an expensive database trip.
+ // We're using an SQLite in-memory database (with "Code First" approach) that goes away when the process ends.
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Sample showing EF Core Resultset caching with NCache to save expensive database trips.\n");
+
+ using (var dbContext = new CustomersbContext(args[0]))
+ {
+ dbContext.Database.EnsureCreated();
+ dbContext.Database.Migrate();
+
+ // Cache the entire query resultset as one item in the cache
+ var cachingOptionsAlfki = new CachingOptions { StoreAs = StoreAs.Collection };
+ cachingOptionsAlfki.SetAbsoluteExpiration(DateTime.Now.AddMinutes(5));
+
+ // .FromCache() Extension Method fetches the resultset from the cache. If not found,
+ // it caches it automatically. We are caching with 5min expiration.
+
+ // This is the first call so resultset is obtained from the database
+ var alFKICustomer = dbContext.Customers.Where(c => c.CustomerID == "ALFKI")
+ .FromCache(cachingOptionsAlfki).FirstOrDefault();
+
+ Console.WriteLine("Loaded customer ALFKI from the database and cached...5min expiration");
+
+ if (alFKICustomer != null)
+ PrintCustomerDetails(alFKICustomer);
+
+ // This is the second call to .FromCache() so resultset is fetched from the cache
+ alFKICustomer = dbContext.Customers.Where(c => c.CustomerID == "ALFKI")
+ .FromCache(cachingOptionsAlfki).FirstOrDefault();
+
+ if (alFKICustomer != null)
+ {
+ Console.WriteLine("Found and retrieved customer ALFKI from the cache...");
+ PrintCustomerDetails(alFKICustomer);
+ }
+
+ Console.WriteLine("Sample completed successfully.");
+ }
+ }
+
+ static void PrintCustomerDetails(Customer customer)
+ {
+ if (customer != null)
+ {
+ Console.WriteLine("CustomerID, Company, City, Country");
+ Console.WriteLine($"- {customer.CustomerID}, {customer.CompanyName}, {customer.City}, {customer.Country}");
+ }
+ Console.WriteLine();
+ }
+ }
+
+ public class CustomersbContext : DbContext
+ {
+ public string _cacheName;
+ public DbSet Customers { get; set; }
+
+ public CustomersbContext(string cacheName)
+ {
+ _cacheName = cacheName;
+ }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ string cacheId = _cacheName;
+
+ Console.WriteLine($"Connecting to cache: {cacheId}\n");
+ NCacheConfiguration.Configure(cacheId, DependencyType.Other);
+ Console.WriteLine($"Connected to Cache successfully: {cacheId}\n");
+
+ // Configure in-memory database using SQLite provider
+ var connection = new SqliteConnection("Data Source=:memory:");
+ connection.Open();
+ optionsBuilder.UseSqlite(connection);
+
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ // Seed dummy data for demonstration purposes
+ modelBuilder.Entity().HasData(
+ new Customer { CustomerID = "ALFKI", CompanyName = "Alfreds Futterkiste", City = "Berlin", Country = "Germany" },
+ new Customer { CustomerID = "GREAL", CompanyName = "Great Lakes Food Market", City = "Eugene", Country = "USA" }
+ );
+ }
+ }
+
+ [Serializable]
+ public class Customer
+ {
+ public string CustomerID { get; set; }
+ public string CompanyName { get; set; }
+ public string City { get; set; }
+ public string Country { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/EFCoreResultsetCaching/Code/Properties/launchSettings.json b/playground/dotnetcore/EFCoreResultsetCaching/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..5264d1e
--- /dev/null
+++ b/playground/dotnetcore/EFCoreResultsetCaching/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "EfCoreResultsetCaching": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/GroupingCachedData/Code/GroupingCachedData.csproj b/playground/dotnetcore/GroupingCachedData/Code/GroupingCachedData.csproj
new file mode 100644
index 0000000..3c2c35f
--- /dev/null
+++ b/playground/dotnetcore/GroupingCachedData/Code/GroupingCachedData.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
diff --git a/playground/dotnetcore/GroupingCachedData/Code/Program.cs b/playground/dotnetcore/GroupingCachedData/Code/Program.cs
new file mode 100644
index 0000000..3c7da62
--- /dev/null
+++ b/playground/dotnetcore/GroupingCachedData/Code/Program.cs
@@ -0,0 +1,98 @@
+using Alachisoft.NCache.Client;
+using Alachisoft.NCache.Runtime.Caching;
+
+namespace NCache.Playground.Samples.GroupingCachedData
+{
+ // Use the Tags feature of NCache to group items. First, use Tags while adding to the cache. Later, fetch by Tags
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Sample showing the Tags feature of NCache to logically group related data to easily fetch later.\n");
+
+ // Connect to the cache
+ string cacheName = args[0];
+
+ Console.WriteLine($"Connecting to cache: {cacheName}");
+ // Connect to the cache and return a cache handle
+ var cache = CacheManager.GetCache(cacheName);
+ Console.WriteLine($"Cache connected successfully: {cacheName}\n");
+
+ var laptop = new Product { ProductID = 12001, Name = "Laptop", Price = 2000, Category = "Electronics" };
+ var kindle = new Product { ProductID = 12002, Name = "Kindle", Price = 1000, Category = "Electronics" };
+ var book = new Product { ProductID = 12003, Name = "Book", Price = 100, Category = "Stationery" };
+ var smartPhone = new Product { ProductID = 12004, Name = "Smart Phone", Price = 1000, Category = "Electronics" };
+ var mobilePhone = new Product { ProductID = 12005, Name = "Mobile Phone", Price = 200, Category = "Electronics" };
+
+ var laptopCacheItem = new CacheItem(laptop) { Tags = new[] { new Tag("Technology"), new Tag("Gadgets") } };
+ var kindleCacheItem = new CacheItem(kindle) { Tags = new[] { new Tag("Technology"), new Tag("Reading") } };
+ var bookCacheItem = new CacheItem(book) { Tags = new[] { new Tag("Education"), new Tag("Reading") } };
+ var smartPhoneCacheItem = new CacheItem(smartPhone) { Tags = new[] { new Tag("Technology"), new Tag("Communication") } };
+ var mobilePhoneCacheItem = new CacheItem(mobilePhone) { Tags = new[] { new Tag("Technology"), new Tag("Communication") } };
+
+ var products = new Dictionary
+ {
+ { "12001", laptopCacheItem },
+ { "12002", kindleCacheItem },
+ { "12003", bookCacheItem },
+ { "12004", smartPhoneCacheItem },
+ { "12005", mobilePhoneCacheItem }
+ };
+
+ // Add all the products to the cache.
+ foreach (var product in products)
+ {
+ cache.Insert(product.Key, product.Value);
+ }
+ Console.WriteLine("Products added to the cache successfully.\n");
+
+ var technologyItems = cache.SearchService.GetByTag(new Tag("Technology"));
+
+ Console.WriteLine("Got Items from the cache by Tag \"Technology\"");
+ PrintProductDetails(technologyItems);
+
+ // Get all items from the cache with this Tag. readingItems is a list of key-value pairs
+ var readingItems = cache.SearchService.GetByTag(new Tag("Reading"));
+
+ Console.WriteLine("Got the Items from the cache by Tag \"Reading\"");
+ PrintProductDetails(readingItems);
+
+ // Create an array of tags
+ Tag[] tags = new[] { new Tag("Technology"), new Tag("Reading") };
+
+ // Remove all items from the cache with any of the tags
+ cache.SearchService.RemoveByTags(tags, TagSearchOptions.ByAnyTag);
+ Console.WriteLine("Removed Items by Tags \"Technology\" and \"Reading\"\n");
+
+ Console.WriteLine("Sample completed successfully.");
+ }
+
+ static void PrintProductDetails(IEnumerable> items)
+ {
+ if (items != null && items.Any())
+ {
+ Console.WriteLine("ProductID, Name, Price, Category");
+ foreach (var cacheItem in items)
+ {
+ var product = cacheItem.Value;
+ Console.WriteLine($"- {product.ProductID}, {product.Name}, ${product.Price}, {product.Category}");
+ }
+ }
+ else
+ {
+ Console.WriteLine("No items found...");
+ }
+ Console.WriteLine();
+ }
+ }
+
+ [Serializable]
+ public class Product
+ {
+ public int ProductID { get; set; }
+ public string Name { get; set; }
+ public decimal Price { get; set; }
+ public string Category { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/GroupingCachedData/Code/Properties/launchSettings.json b/playground/dotnetcore/GroupingCachedData/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..7274640
--- /dev/null
+++ b/playground/dotnetcore/GroupingCachedData/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "GroupingCachedData": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/NCachePlaygroundSamples.sln b/playground/dotnetcore/NCachePlaygroundSamples.sln
new file mode 100644
index 0000000..61b3c2f
--- /dev/null
+++ b/playground/dotnetcore/NCachePlaygroundSamples.sln
@@ -0,0 +1,67 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32210.238
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicCacheOperations", "BasicCacheOperations\Code\BasicCacheOperations.csproj", "{3404E096-E710-4067-B824-40D5CBFA0C48}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheItemLocking", "CacheItemLocking\Code\CacheItemLocking.csproj", "{B78E386E-C114-4E11-8816-6ED088B7F24A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GroupingCachedData", "GroupingCachedData\Code\GroupingCachedData.csproj", "{E0A5C4E5-900E-4A46-8BB2-489A6EEBAE58}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EfCoreResultsetCaching", "EFCoreResultsetCaching\Code\EfCoreResultsetCaching.csproj", "{CAAD57B4-29FB-4D3A-91BD-64E18A985C7A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqlQueryCacheLookup", "SqlQueryCacheLookup\Code\SqlQueryCacheLookup.csproj", "{B67C5C42-EC23-46AA-B237-BC8642560D18}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EfCoreLinqCacheLookup", "EFCoreLinqCacheLookup\Code\EfCoreLinqCacheLookup.csproj", "{C7C214BA-D588-4F0F-A449-E657266A7337}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStructures", "DataStructures\Code\DataStructures.csproj", "{8A24B984-80C4-4FCD-9F85-05C533D524EC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PubSubMessaging", "PubSubMessaging\Code\PubSubMessaging.csproj", "{581EE271-EBF6-4ECD-A4AF-9C86EC7B0162}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3404E096-E710-4067-B824-40D5CBFA0C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3404E096-E710-4067-B824-40D5CBFA0C48}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3404E096-E710-4067-B824-40D5CBFA0C48}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3404E096-E710-4067-B824-40D5CBFA0C48}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B78E386E-C114-4E11-8816-6ED088B7F24A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B78E386E-C114-4E11-8816-6ED088B7F24A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B78E386E-C114-4E11-8816-6ED088B7F24A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B78E386E-C114-4E11-8816-6ED088B7F24A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E0A5C4E5-900E-4A46-8BB2-489A6EEBAE58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0A5C4E5-900E-4A46-8BB2-489A6EEBAE58}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E0A5C4E5-900E-4A46-8BB2-489A6EEBAE58}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E0A5C4E5-900E-4A46-8BB2-489A6EEBAE58}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CAAD57B4-29FB-4D3A-91BD-64E18A985C7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CAAD57B4-29FB-4D3A-91BD-64E18A985C7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CAAD57B4-29FB-4D3A-91BD-64E18A985C7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CAAD57B4-29FB-4D3A-91BD-64E18A985C7A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B67C5C42-EC23-46AA-B237-BC8642560D18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B67C5C42-EC23-46AA-B237-BC8642560D18}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B67C5C42-EC23-46AA-B237-BC8642560D18}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B67C5C42-EC23-46AA-B237-BC8642560D18}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C7C214BA-D588-4F0F-A449-E657266A7337}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C7C214BA-D588-4F0F-A449-E657266A7337}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C7C214BA-D588-4F0F-A449-E657266A7337}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C7C214BA-D588-4F0F-A449-E657266A7337}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8A24B984-80C4-4FCD-9F85-05C533D524EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8A24B984-80C4-4FCD-9F85-05C533D524EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8A24B984-80C4-4FCD-9F85-05C533D524EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8A24B984-80C4-4FCD-9F85-05C533D524EC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {581EE271-EBF6-4ECD-A4AF-9C86EC7B0162}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {581EE271-EBF6-4ECD-A4AF-9C86EC7B0162}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {581EE271-EBF6-4ECD-A4AF-9C86EC7B0162}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {581EE271-EBF6-4ECD-A4AF-9C86EC7B0162}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {32D69342-C0D9-42E5-AD2C-689F0D099C2C}
+ EndGlobalSection
+EndGlobal
diff --git a/playground/dotnetcore/PubSubMessaging/Code/Program.cs b/playground/dotnetcore/PubSubMessaging/Code/Program.cs
new file mode 100644
index 0000000..c5f2d4f
--- /dev/null
+++ b/playground/dotnetcore/PubSubMessaging/Code/Program.cs
@@ -0,0 +1,138 @@
+using Alachisoft.NCache.Client;
+using Alachisoft.NCache.Runtime.Caching;
+
+namespace NCache.Playground.Samples.PubSubMessaging
+{
+ // Use NCache Pub/Sub Messaging in this sample. In NCache, you can create multiple Topics
+ // and against each topic create multiple publishers and subscribers. In this sample,
+ // 2 parallel Async publisher tasks publish on the same topic and 2 subscribers receive
+ // messages from this topic. All messages use DeliveryOption. Any so only one subscriber
+ // gets each message. DeliveryOption.All is available but not used.
+
+ class Program
+ {
+ static string topicName = "ORDERS";
+ static readonly object consoleLock = new object();
+ static async Task Main(string[] args)
+ {
+ Console.WriteLine("Sample showing NCache Pub/Sub Messaging for reliable real-time messaging between publishers and subscribers.\n");
+
+ var cacheName = args[0];
+
+ Console.WriteLine($"Connecting to cache: {cacheName}\n");
+ // Connect to the cache and return a cache handle
+ var cache = CacheManager.GetCache(cacheName);
+ Console.WriteLine($"Connected to Cache successfully: {cacheName}\n");
+
+ Console.WriteLine($"Create a Topic {topicName} ...\n");
+
+ // Create a Topic in NCache.
+ var topic = cache.MessagingService.CreateTopic(topicName);
+
+ Console.WriteLine("Register 2 subscribers for Topic " + topicName + "\n");
+
+ // Register subscribers to this Topic
+ var subscription1 = topic.CreateSubscription(MessageReceived_Subscription1);
+ var subscription2 = topic.CreateSubscription(MessageReceived_Subscription2);
+
+ // Create first asynchronous publisher task to publish 2 messages
+ var publisher1Task = new Task(async () =>
+ {
+ var message1 = new Message
+ (
+ new Order() { OrderID = 17348, Customer = "Vins et alcools Chevalier", OrderDate = DateTime.Parse("04-Jul-1997"), ShipVia = "Federal Shipping" }
+ );
+
+ var message2 = new Message
+ (
+ new Order() { OrderID = 17350, Customer = "Hanari Carnes", OrderDate = DateTime.Parse("07-Jul-1997"), ShipVia = "United Package" }
+ );
+
+ PrintMessage(message1, "Publisher 1", null);
+ // "Any" means that only one subscriber will receive this message
+ // Another option is "All" where all subscribers recieve the message
+ topic.Publish(message1, DeliveryOption.Any);
+
+ // wait for 1sec before publishing again
+ Thread.Sleep(1000);
+ PrintMessage(message2, "Publisher 1", null);
+
+ topic.Publish(message2, DeliveryOption.Any);
+ });
+
+ // Create second asynchronous publisher task to publish 2 messages
+ var publisher2Task = new Task(async () =>
+ {
+ var message1 = new Message
+ (
+ new Order() { OrderID = 17349, Customer = "Toms Spezialitäten", OrderDate = DateTime.Parse("05-Jul-1997"), ShipVia = "Speedy Express" }
+ );
+
+ var message2 = new Message
+ (
+ new Order() { OrderID = 17351, Customer = "Victuailles en stock", OrderDate = DateTime.Parse("08-Jul-1997"), ShipVia = "Speedy Express" }
+ );
+
+ PrintMessage(message1, "Publisher 2", null);
+
+ // "Any" means that only one subscriber will receive this message
+ // Another option is "All" where all subscribers recieve the message
+ topic.Publish(message1, DeliveryOption.Any);
+
+ // wait for 1sec before publishing again
+ Thread.Sleep(1000);
+ PrintMessage(message2, "Publisher 2", null);
+
+ topic.Publish(message2, DeliveryOption.Any);
+ });
+
+ // Now start both Async publisher tasks so each can publish 2 messages in parallel
+ publisher1Task.Start();
+ publisher2Task.Start();
+
+ // Wait for 5sec
+ Thread.Sleep(5000);
+
+ // Waiting for both publisher tasks to complete so we can end the sample
+ await Task.WhenAll(publisher1Task, publisher2Task);
+
+ subscription1.UnSubscribe();
+ subscription2.UnSubscribe();
+
+ Console.WriteLine("Sample completed successfully.");
+ }
+
+ private static void MessageReceived_Subscription1(object sender, MessageEventArgs args)
+ {
+ PrintMessage(args.Message, null, "Subscriber 1");
+ }
+
+ private static void MessageReceived_Subscription2(object sender, MessageEventArgs args)
+ {
+ PrintMessage(args.Message, null, "Subscriber 2");
+ }
+
+ static void PrintMessage(IMessage message, string sender, string receiver)
+ {
+ var order = message.Payload as Order;
+
+ lock (consoleLock)
+ {
+ if (!string.IsNullOrEmpty(sender)) Console.WriteLine($"{sender} publishes a message for Topic {topicName} ...");
+ else if (!string.IsNullOrEmpty(receiver)) Console.WriteLine($"{receiver} receives message ...");
+
+ Console.WriteLine("OrderID, Customer, Order Date, Ship Via");
+ Console.WriteLine($"- {order.OrderID}, {order.Customer}, {order.OrderDate.ToString("dd-MMM-yyyy")}, {order.ShipVia} \n");
+ }
+ }
+ }
+
+ [Serializable]
+ public class Order
+ {
+ public int OrderID { get; set; }
+ public string Customer { get; set; }
+ public DateTime OrderDate { get; set; }
+ public string ShipVia { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/PubSubMessaging/Code/Properties/launchSettings.json b/playground/dotnetcore/PubSubMessaging/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..eac1bd6
--- /dev/null
+++ b/playground/dotnetcore/PubSubMessaging/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "PubSubMessaging": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/PubSubMessaging/Code/PubSubMessaging.csproj b/playground/dotnetcore/PubSubMessaging/Code/PubSubMessaging.csproj
new file mode 100644
index 0000000..3c2c35f
--- /dev/null
+++ b/playground/dotnetcore/PubSubMessaging/Code/PubSubMessaging.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
diff --git a/playground/dotnetcore/SqlQueryCacheLookup/Code/Program.cs b/playground/dotnetcore/SqlQueryCacheLookup/Code/Program.cs
new file mode 100644
index 0000000..4e263da
--- /dev/null
+++ b/playground/dotnetcore/SqlQueryCacheLookup/Code/Program.cs
@@ -0,0 +1,180 @@
+using System.Collections;
+using Alachisoft.NCache.Client;
+using Alachisoft.NCache.Runtime.Caching;
+
+namespace NCache.Playground.Samples.SqlQueryCacheLookup
+{
+ // Use SQL to query for cached data in NCache based on object attributes and Tags instead of just keys.
+ // NCache SQL query requires indexes to be created on all objects being searched. One way is
+ // thru cache configuration. Second is through code using "Custom Attributes" to annotate object fields
+ // and create index on them automatically when they're added to the cache.
+ // In this sample, we're using "Custom Attributes" to create index on Product object.
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Sample showing SQL queries to find data in NCache based on object attributes instead of keys.\n");
+
+ string cacheName = args[0];
+
+ Console.WriteLine($"Connecting to cache: {cacheName}");
+ // Connect to the cache and return a cache handle
+ var cache = CacheManager.GetCache(cacheName);
+ Console.WriteLine($"Cache connected successfully: {cacheName}\n");
+
+ // Adds all the products to the cache. This automatically creates indexes on various
+ // attributes of Product object by using "Custom Attributes".
+ AddSampleData(cache);
+
+ Console.WriteLine("Find products with Category IN (\"Electronics\", \"Stationery\") AND Price < $2000");
+
+ // $VALUE$ keyword means the entire object instead of individual attributes that are also possible
+ string sql = $"SELECT $VALUE$ FROM NCache.Playground.Samples.SqlQueryCacheLookup.Product WHERE Category IN (?, ?) AND Price < ?";
+
+ var sqlCommand = new QueryCommand(sql);
+
+ ArrayList catParamList = new ArrayList();
+ catParamList.Add("Electronics");
+ catParamList.Add("Stationery");
+
+ sqlCommand.Parameters.Add("Category", catParamList);
+ sqlCommand.Parameters.Add("Price", new Decimal(2000));
+
+ // ExecuteReader returns ICacheReader with the query resultset
+ using (var reader = cache.SearchService.ExecuteReader(sqlCommand))
+ {
+ var fetchedProducts = new List();
+ if (reader.FieldCount > 0)
+ {
+ while (reader.Read())
+ {
+ // GetValue() with $VALUE$ keyword returns the entire object instead of just one column
+ var result = reader.GetValue("$VALUE$");
+
+ fetchedProducts.Add(result);
+ }
+ }
+ PrintProducts(fetchedProducts);
+ }
+
+ Console.WriteLine("Find all \"phone\" products (using LIKE operator) AND (Tag = \"Technology\" OR Tag = \"Gadgets\")");
+ sql = $"SELECT $VALUE$ FROM NCache.Playground.Samples.SqlQueryCacheLookup.Product WHERE Name LIKE ? AND ($Tag$ = ? OR $Tag$ = ?)";
+
+ sqlCommand = new QueryCommand(sql);
+
+ ArrayList tagList = new ArrayList();
+ tagList.Add("Technology");
+ tagList.Add("Gadgets");
+
+ sqlCommand.Parameters.Add("Name", "*Phone*");
+ sqlCommand.Parameters.Add("$Tag$", tagList);
+
+ using (var reader = cache.SearchService.ExecuteReader(sqlCommand))
+ {
+ var fetchedProducts = new List();
+ if (reader.FieldCount > 0)
+ {
+ while (reader.Read())
+ {
+ var result = reader.GetValue("$VALUE$");
+ fetchedProducts.Add(result);
+ }
+ }
+ PrintProducts(fetchedProducts);
+ }
+
+ Console.WriteLine("GROUP BY query: Get a count of product by category with Price < $3000");
+ sql = $"SELECT Category, COUNT(*) FROM NCache.Playground.Samples.SqlQueryCacheLookup.Product WHERE Price < ? GROUP BY Category";
+
+ sqlCommand = new QueryCommand(sql);
+
+ sqlCommand.Parameters.Add("Price", new Decimal(3000));
+
+ using (var reader = cache.SearchService.ExecuteReader(sqlCommand))
+ {
+ Console.WriteLine("Category, Count");
+ if (reader.FieldCount > 0)
+ {
+ while (reader.Read())
+ {
+ var category = reader.GetValue("Category");
+ var count = reader.GetValue("COUNT()");
+ Console.WriteLine($"- {category}, {count}");
+ }
+ }
+ }
+
+ Console.WriteLine("\nDelete Items by Tags \"Technology\" and \"Reading\"");
+ ArrayList removeTagsList = new ArrayList();
+ removeTagsList.Add("Technology");
+ removeTagsList.Add("Reading");
+
+ sql = "DELETE FROM NCache.Playground.Samples.SqlQueryCacheLookup.Product WHERE $Tag$ IN (?, ?)";
+ sqlCommand = new QueryCommand(sql);
+ sqlCommand.Parameters.Add("$Tag$", removeTagsList);
+ var itemAffected = cache.SearchService.ExecuteNonQuery(sqlCommand);
+ Console.WriteLine($"{itemAffected} items removed from the cache.\n");
+
+ Console.WriteLine("Sample completed successfully.");
+ }
+
+ static void AddSampleData(ICache cache)
+ {
+ Console.WriteLine("Adding products to the cache with tags...");
+
+ var laptop = new Product { ProductID = 13001, Name = "Laptop", Price = 2000, Category = "Electronics" };
+ var kindle = new Product { ProductID = 13002, Name = "Kindle", Price = 1000, Category = "Electronics" };
+ var book = new Product { ProductID = 13003, Name = "Book", Price = 100, Category = "Stationery" };
+ var smartPhone = new Product { ProductID = 13004, Name = "Smart Phone", Price = 1000, Category = "Electronics" };
+ var mobilePhone = new Product { ProductID = 13005, Name = "Mobile Phone", Price = 200, Category = "Electronics" };
+
+ var laptopCacheItem = new CacheItem(laptop) { Tags = new[] { new Tag("Technology"), new Tag("Gadgets") } };
+ var kindleCacheItem = new CacheItem(kindle) { Tags = new[] { new Tag("Technology"), new Tag("Reading") } };
+ var bookCacheItem = new CacheItem(book) { Tags = new[] { new Tag("Education"), new Tag("Reading") } };
+ var smartPhoneCacheItem = new CacheItem(smartPhone) { Tags = new[] { new Tag("Technology"), new Tag("Communication") } };
+ var mobilePhoneCacheItem = new CacheItem(mobilePhone) { Tags = new[] { new Tag("Technology"), new Tag("Communication") } };
+
+ var products = new Dictionary
+ {
+ { "13001", laptopCacheItem },
+ { "13002", kindleCacheItem },
+ { "13003", bookCacheItem },
+ { "13004", smartPhoneCacheItem },
+ { "13005", mobilePhoneCacheItem }
+ };
+
+ // Adds all the products to the cache. This automatically creates indexes on various
+ // attributes of Product object by using "Custom Attributes".
+ foreach (var product in products)
+ {
+ cache.Insert(product.Key, product.Value);
+ }
+
+ var productValues = products.Values.Select(cacheItem => cacheItem.GetValue());
+ PrintProducts(productValues);
+ }
+
+ static void PrintProducts(IEnumerable products)
+ {
+ Console.WriteLine("ProductID, Name, Price, Category");
+ foreach (var product in products)
+ {
+ Console.WriteLine($"- {product.ProductID}, {product.Name}, ${product.Price}, {product.Category}");
+ }
+ Console.WriteLine();
+ }
+ }
+
+ [Serializable]
+ public class Product
+ {
+ public int ProductID { get; set; }
+ [QueryIndexed]
+ public string Name { get; set; }
+ [QueryIndexed]
+ public decimal Price { get; set; }
+ [QueryIndexed]
+ public string Category { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/SqlQueryCacheLookup/Code/Properties/launchSettings.json b/playground/dotnetcore/SqlQueryCacheLookup/Code/Properties/launchSettings.json
new file mode 100644
index 0000000..03bfdb2
--- /dev/null
+++ b/playground/dotnetcore/SqlQueryCacheLookup/Code/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "SqlQueryCacheLookup": {
+ "commandName": "Project",
+ "commandLineArgs": "demoCache"
+ }
+ }
+}
\ No newline at end of file
diff --git a/playground/dotnetcore/SqlQueryCacheLookup/Code/SqlQueryCacheLookup.csproj b/playground/dotnetcore/SqlQueryCacheLookup/Code/SqlQueryCacheLookup.csproj
new file mode 100644
index 0000000..e5d4b1d
--- /dev/null
+++ b/playground/dotnetcore/SqlQueryCacheLookup/Code/SqlQueryCacheLookup.csproj
@@ -0,0 +1,30 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ bin\
+ false
+ false
+ Exe
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
diff --git a/playground/java/BasicCacheOperations/Code/pom.xml b/playground/java/BasicCacheOperations/Code/pom.xml
new file mode 100644
index 0000000..f53983f
--- /dev/null
+++ b/playground/java/BasicCacheOperations/Code/pom.xml
@@ -0,0 +1,69 @@
+
+
+ 4.0.0
+
+
+
+ com.alachisoft.ncache.samples
+ BasicCacheOperations
+ 5.3.0
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.alachisoft.ncache
+ ncache-client
+ ${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/BasicCacheOperations/Code/src/main/java/com/alachisoft/ncache/samples/BasicCacheOperations.java b/playground/java/BasicCacheOperations/Code/src/main/java/com/alachisoft/ncache/samples/BasicCacheOperations.java
new file mode 100644
index 0000000..174f60f
--- /dev/null
+++ b/playground/java/BasicCacheOperations/Code/src/main/java/com/alachisoft/ncache/samples/BasicCacheOperations.java
@@ -0,0 +1,89 @@
+package com.alachisoft.ncache.samples;
+
+import java.io.Serializable;
+import com.alachisoft.ncache.client.*;
+import com.alachisoft.ncache.runtime.caching.expiration.*;
+import com.alachisoft.ncache.runtime.util.TimeSpan;
+
+// Basic caching operations (CRUD) as an intro to NCache API
+
+public class BasicCacheOperations {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("Sample showing basic caching operations (CRUD) in NCache, along with expiration.\n");
+
+ String cacheName = args[0];
+ System.out.println("Connecting to cache: " + cacheName);
+
+ CacheConnectionOptions connectionOptions = new CacheConnectionOptions();
+ connectionOptions.setIsolationLevel(IsolationLevel.OutProc);
+
+ // Connect to the cache and return a cache handle
+ Cache cache = CacheManager.getCache(cacheName, connectionOptions);
+ System.out.println("Connected to Cache successfully: " + cacheName + "\n");
+
+ // Add product 10001 to the cache with a 5-minutes expiration
+ Product prod1 = new Product(10001, "Laptop", 1000, "Electronics");
+
+ String prod1Key = String.valueOf(prod1.getProductID());
+ CacheItem productCacheItem = new CacheItem(prod1);
+ productCacheItem.setExpiration(new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5)));
+
+ // Add to the cache with 5min absolute expiration (TTL). Item expires automatically
+ cache.add(prod1Key, productCacheItem);
+
+ System.out.println("Product 10001 added successfully (5min expiration):");
+ printProductDetails(prod1);
+
+ // Get from the cache. If not found, a null is returned
+ Product retrievedprod1 = cache.get(prod1Key, Product.class);
+ if (retrievedprod1 != null) {
+ System.out.println("Product 10001 retrieved successfully:");
+ printProductDetails(retrievedprod1);
+ }
+
+ retrievedprod1.setPrice(3000);
+
+ // Update product in the cache. If not found, it is added
+ CacheItem updatedProductCacheItem = new CacheItem(retrievedprod1);
+ updatedProductCacheItem.setExpiration(new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5)));
+ cache.insert(prod1Key, updatedProductCacheItem);
+
+ System.out.println("Price for Product 10001 updated successfully:");
+ printProductDetails(retrievedprod1);
+
+ // Remove the item from the cache
+ cache.delete(prod1Key);
+ System.out.println("Deleted the product " + prod1Key + " from the cache...\n");
+
+ System.out.println("Sample completed successfully.");
+ cache.close();
+ }
+
+ private static void printProductDetails(Product product) {
+ System.out.println("ProductID, Name, Price, Category");
+ System.out.println("- " + product.getProductID() + ", " + product.getName() + ", " + product.getPrice() + ", " + product.getCategory() + "\n");
+ }
+}
+
+// Sample class for Product
+class Product implements Serializable {
+ private int productID;
+ private String name;
+ private int price;
+ private String category;
+
+ public Product(int productID, String name, int price, String category) {
+ this.productID = productID;
+ this.name = name;
+ this.price = price;
+ this.category = category;
+ }
+
+ public int getProductID() { return productID; }
+ public String getName() { return name; }
+ public double getPrice() { return price; }
+ public void setPrice(int price) { this.price = price; }
+ public String getCategory() { return category; }
+}
\ No newline at end of file
diff --git a/playground/java/CacheItemLocking/Code/pom.xml b/playground/java/CacheItemLocking/Code/pom.xml
new file mode 100644
index 0000000..9e864ab
--- /dev/null
+++ b/playground/java/CacheItemLocking/Code/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+
+
+ com.alachisoft.ncache.samples
+ CacheItemLocking
+ 5.3.0
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.alachisoft.ncache
+ ncache-client
+ ${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/CacheItemLocking/Code/src/main/java/com/alachisoft/ncache/samples/CacheItemLocking.java b/playground/java/CacheItemLocking/Code/src/main/java/com/alachisoft/ncache/samples/CacheItemLocking.java
new file mode 100644
index 0000000..b672928
--- /dev/null
+++ b/playground/java/CacheItemLocking/Code/src/main/java/com/alachisoft/ncache/samples/CacheItemLocking.java
@@ -0,0 +1,88 @@
+package com.alachisoft.ncache.samples;
+
+import java.io.Serializable;
+import com.alachisoft.ncache.client.Cache;
+import com.alachisoft.ncache.client.CacheItem;
+import com.alachisoft.ncache.client.CacheManager;
+import com.alachisoft.ncache.client.LockHandle;
+import com.alachisoft.ncache.runtime.caching.WriteThruOptions;
+import com.alachisoft.ncache.runtime.util.TimeSpan;
+
+// Locking an item prevents other users from accessing it while you update it.
+// You can lock with cache.GetCacheItem() or cache.Lock() and unlock with cache.Insert() or cache.Unlock()
+// NOTE: Locking API is for application level locking. NCache already has its own internal locking
+// for concurrency and thread-safe operations.
+
+public class CacheItemLocking {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("Sample showing item level lock and unlock in NCache.\n");
+ String cacheName = args[0];
+
+ System.out.println("Connecting to cache: " + cacheName);
+ // Connect to the cache and return a cache handle
+ Cache cache = CacheManager.getCache(cacheName);
+ System.out.println("Connected to Cache successfully: " + cacheName + "\n");
+
+ Product prod1 = new Product(11001, "Laptop", 1000, "Electronics");
+
+ String prod1Key = String.valueOf(prod1.getProductID());
+ System.out.println("Adding product 11001 to the cache...");
+
+ // Add a product to the cache. If it already exists, the operation will fail
+ cache.insert(prod1Key, prod1);
+ System.out.println("Product added successfully:");
+ printProductDetails(prod1);
+
+ // Get product 11001 and lock it in the cache
+ System.out.println("Get and lock product 11001 in the cache...");
+ LockHandle lockHandle = new LockHandle();
+
+ // Lock the item and set a lock timeout of 10 seconds
+ CacheItem lockedCacheItem = cache.getCacheItem(prod1Key, true, TimeSpan.FromSeconds(10), lockHandle);
+ if (lockedCacheItem != null) {
+ System.out.println("Product 11001 retrieved and locked successfully:");
+ Product retrievedProduct = (Product) lockedCacheItem.getValue(Product.class);
+ printProductDetails(retrievedProduct);
+
+ // Change the price of product 11001
+ retrievedProduct.setPrice(2000);
+
+ // Update the item and release the lock
+ cache.insert(prod1Key, lockedCacheItem, new WriteThruOptions(), lockHandle, true);
+ System.out.println("Updated price of product 11001 and released the lock simultaneously in the cache...");
+
+ printProductDetails(retrievedProduct);
+ }
+ System.out.println("Sample completed successfully.");
+ cache.close();
+ }
+
+ private static void printProductDetails(Product product) {
+ System.out.println("ProductID, Name, Price, Category");
+ System.out.println("- " + product.getProductID() + ", " + product.getName() + ", " + product.getPrice() + ", " + product.getCategory() + "\n");
+ }
+}
+
+// Sample class for Product
+class Product implements Serializable {
+ private int productID;
+ private String name;
+ private int price;
+ private String category;
+
+ public Product(int productID, String name, int price, String category) {
+ this.productID = productID;
+ this.name = name;
+ this.price = price;
+ this.category = category;
+ }
+
+ public int getProductID() { return productID; }
+ public String getName() { return name; }
+ public double getPrice() { return price;}
+ public void setPrice(int price) { this.price = price;}
+ public String getCategory() { return category;}
+
+}
diff --git a/playground/java/DataStructures/Code/pom.xml b/playground/java/DataStructures/Code/pom.xml
new file mode 100644
index 0000000..8d63339
--- /dev/null
+++ b/playground/java/DataStructures/Code/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+
+
+ com.alachisoft.ncache.samples
+ DataStructures
+ 5.3.0
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.alachisoft.ncache
+ ncache-client
+ ${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/DataStructures/Code/src/main/java/com/alachisoft/ncache/samples/DataStructures.java b/playground/java/DataStructures/Code/src/main/java/com/alachisoft/ncache/samples/DataStructures.java
new file mode 100644
index 0000000..e70d35f
--- /dev/null
+++ b/playground/java/DataStructures/Code/src/main/java/com/alachisoft/ncache/samples/DataStructures.java
@@ -0,0 +1,155 @@
+package com.alachisoft.ncache.samples;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import com.alachisoft.ncache.client.*;
+import com.alachisoft.ncache.client.datastructures.DistributedList;
+import com.alachisoft.ncache.client.datastructures.DistributedQueue;
+
+// Use NCache distributed data structures (List and Queue in this sample). NCache provides
+// Set, Dictionary, and Counter data structures as well. These data structures are distributed in the cluster
+// for scalability and accessible to all clients.
+
+public class DataStructures {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("Sample showing distributed data structures in NCache (List, Queue) for more powerful data management.\n");
+
+ String cacheName = args[0];
+
+ System.out.println("Connecting to cache: " + cacheName);
+ // Connect to the cache and return a cache handle
+ Cache cache = CacheManager.getCache(cacheName);
+ System.out.println("Connected to Cache successfully: " + cacheName + "\n");
+ System.out.println("Create a List data structure and add products 'Electronics' to it...");
+
+ // Get the list if it already exists in the cache
+ DistributedList productList = cache.getDataStructuresManager().getList("productList", Product.class);
+
+ if (productList == null) {
+ // Create a List data structure in the cache and then add products to it
+ productList = cache.getDataStructuresManager().createList("productList", Product.class);
+ }
+
+ // These products are directly added to the cache inside the List data structure when you add them below
+ productList.add(new Product(15001, "Laptop", BigDecimal.valueOf(2000), "Electronics"));
+ productList.add(new Product(15002, "Kindle", BigDecimal.valueOf(1000), "Electronics"));
+ productList.add(new Product(15004, "Smart Phone", BigDecimal.valueOf(1000), "Electronics"));
+ productList.add(new Product(15005, "Mobile Phone", BigDecimal.valueOf(200), "Electronics"));
+
+ printProductList(productList);
+
+ System.out.println("Create a Queue data structure and add orders to it...");
+
+ // Get the queue if it already exists in the cache
+ DistributedQueue orderQueue = cache.getDataStructuresManager().getQueue("orderQueue", Order.class);
+
+ if (orderQueue == null) {
+ // Create a Queue data structure and then add orders to it by maintaining their sequence
+ orderQueue = cache.getDataStructuresManager().createQueue("orderQueue", Order.class);
+ }
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ // These orders are directly added to the cache inside the Queue data structure when you enqueue them below
+ orderQueue.add(new Order(16248, "Vins et alcools Chevalier", dateFormat.parse("1997-07-04"), "Federal Shipping"));
+ orderQueue.add(new Order(16249, "Toms Spezialitäten", dateFormat.parse("1997-07-05"), "Speedy Express"));
+ orderQueue.add(new Order(16250, "Hanari Carnes", dateFormat.parse("1997-07-07"), "United Package"));
+ orderQueue.add(new Order(16251, "Victuailles en stock", dateFormat.parse("1997-07-08"), "Speedy Express"));
+
+ printOrderQueue(orderQueue);
+
+ System.out.println("Fetch the list and print all items from the List data structure...");
+
+ // Fetch the List data structure from the cache and then access all items in it
+ DistributedList fetchedProductList = cache.getDataStructuresManager().getList("productList", Product.class);
+
+ printProductList(fetchedProductList);
+
+ System.out.println("Process all orders from the Queue one by one in a sequence\n");
+
+ // Fetch the Queue data structure from the cache and then process all orders one by one in a sequence
+ DistributedQueue fetchedOrderQueue = cache.getDataStructuresManager().getQueue("orderQueue", Order.class);
+ while (fetchedOrderQueue.size() > 0) {
+ Order order = orderQueue.poll();
+ System.out.println("Process order : " + order.getOrderID());
+ printOrder(order);
+ }
+
+ // Removing all items from the list
+ productList.removeRange(0, productList.size());
+
+ System.out.println("Removed products from the List data structure.\n");
+
+ System.out.println("Sample completed successfully.");
+ cache.close();
+ }
+
+ static void printProductList(DistributedList productList) {
+ System.out.println("ProductID, Name, Price, Category, Tags");
+ for (Product product : productList) {
+ System.out.println("- " + product.getProductID() + ", " + product.getName() + ", $" + product.getPrice() + ", " + product.getCategory());
+ }
+ System.out.println();
+ }
+
+ static void printOrderQueue(DistributedQueue orderQueue) {
+ System.out.println("OrderID, Customer, Order Date, Ship Via");
+
+ for (Order order : orderQueue) {
+ System.out.println("- " + order.getOrderID() + ", " + order.getCustomer() + ", " + order.getOrderDate().toString() + ", " + order.getShipVia());
+ }
+ System.out.println();
+ }
+
+ static void printOrder(Order order) {
+ System.out.println("OrderID, Customer, Order Date, Ship Via");
+ System.out.println("- " + order.getOrderID() + ", " + order.getCustomer() + ", " + order.getOrderDate().toString() + ", " + order.getShipVia() + "\n");
+ }
+}
+
+// Sample class for Product
+class Product implements Serializable {
+ private int productID;
+ private String name;
+ private BigDecimal price;
+ private String category;
+
+ public Product(){ }
+
+ public Product(int productID, String name, BigDecimal price, String category) {
+ this.productID = productID;
+ this.name = name;
+ this.price = price;
+ this.category = category;
+ }
+
+ public int getProductID() { return productID; }
+ public String getName() { return name; }
+ public BigDecimal getPrice() { return price; }
+ public String getCategory() { return category; }
+}
+
+// Sample class for Order
+class Order implements Serializable {
+ private int orderID;
+ private String customer;
+ private Date orderDate;
+ private String shipVia;
+
+ public Order(){ }
+
+ public Order(int orderID, String customer, Date orderDate, String shipVia) {
+ this.orderID = orderID;
+ this.customer = customer;
+ this.orderDate = orderDate;
+ this.shipVia = shipVia;
+ }
+
+ public int getOrderID() { return orderID; }
+ public String getCustomer() { return customer; }
+ public String getOrderDate() { return new SimpleDateFormat("yyyy-MM-dd").format(orderDate); }
+ public String getShipVia() { return shipVia; }
+}
diff --git a/playground/java/GroupingCachedData/Code/pom.xml b/playground/java/GroupingCachedData/Code/pom.xml
new file mode 100644
index 0000000..09b730a
--- /dev/null
+++ b/playground/java/GroupingCachedData/Code/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+
+
+ com.alachisoft.ncache.samples
+ GroupingCachedData
+ 5.3.0
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.alachisoft.ncache
+ ncache-client
+ ${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/GroupingCachedData/Code/src/main/java/com/alachisoft/ncache/samples/GroupingCachedData.java b/playground/java/GroupingCachedData/Code/src/main/java/com/alachisoft/ncache/samples/GroupingCachedData.java
new file mode 100644
index 0000000..fea7c71
--- /dev/null
+++ b/playground/java/GroupingCachedData/Code/src/main/java/com/alachisoft/ncache/samples/GroupingCachedData.java
@@ -0,0 +1,115 @@
+package com.alachisoft.ncache.samples;
+
+import java.io.Serializable;
+import java.util.*;
+import com.alachisoft.ncache.client.Cache;
+import com.alachisoft.ncache.client.CacheItem;
+import com.alachisoft.ncache.client.CacheManager;
+import com.alachisoft.ncache.client.TagSearchOptions;
+import com.alachisoft.ncache.runtime.caching.Tag;
+
+// Use the Tags feature of NCache to group items. First, use Tags while adding to the cache. Later, fetch by Tags
+
+public class GroupingCachedData {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("Sample showing the Tags feature of NCache to logically group related data to easily fetch later.\n");
+
+ // Connect to the cache
+ String cacheName = args[0];
+
+ System.out.println("Connecting to cache: " + cacheName);
+ // Connect to the cache and return a cache handle
+ Cache cache = CacheManager.getCache(cacheName);
+ System.out.println("Connected to Cache successfully: " + cacheName + "\n");
+
+ Product laptop = new Product(12001, "Laptop", 2000, "Electronics");
+ Product kindle = new Product(12002, "Kindle", 1000, "Electronics");
+ Product book = new Product(12003, "Book", 100, "Stationery");
+ Product smartPhone = new Product(12004, "Smart Phone", 1000, "Electronics");
+ Product mobilePhone = new Product(12005, "Mobile Phone", 200, "Electronics");
+
+ CacheItem laptopCacheItem = new CacheItem(laptop);
+ List laptopTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Gadgets")));
+ laptopCacheItem.setTags(laptopTags);
+
+ CacheItem kindleCacheItem = new CacheItem(kindle);
+ List kindleTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Reading")));
+ kindleCacheItem.setTags(kindleTags);
+
+ CacheItem bookCacheItem = new CacheItem(book);
+ List bookTags = new ArrayList<>(Arrays.asList(new Tag("Education"), new Tag("Reading")));
+ bookCacheItem.setTags(bookTags);
+
+ CacheItem smartPhoneCacheItem = new CacheItem(smartPhone);
+ List smartPhoneTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Communication")));
+ smartPhoneCacheItem.setTags(smartPhoneTags);
+
+ CacheItem mobilePhoneCacheItem = new CacheItem(mobilePhone);
+ List mobilePhoneTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Communication")));
+ mobilePhoneCacheItem.setTags(mobilePhoneTags);
+
+ Map products = new HashMap<>();
+ products.put("12001", laptopCacheItem);
+ products.put("12002", kindleCacheItem);
+ products.put("12003", bookCacheItem);
+ products.put("12004", smartPhoneCacheItem);
+ products.put("12005", mobilePhoneCacheItem);
+
+ // Add all the products to the cache.
+ for (Map.Entry product : products.entrySet()) {
+ cache.insert(product.getKey(), product.getValue());
+ }
+
+ Map technologyItems = cache.getSearchService().getByTag(new Tag("Technology"));
+ System.out.println("Got Items from the cache by Tag \"Technology\"");
+ printProductDetails(technologyItems.values());
+
+ // Get all items from the cache with this Tag. readingItems is a list of key-value pairs
+ Map readingItems = cache.getSearchService().getByTag(new Tag("Reading"));
+ System.out.println("Got the Items from the cache by Tag \"Reading\"");
+ printProductDetails(readingItems.values());
+
+ List tags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Reading")));
+
+ // Remove all items from the cache with any of the tags
+ cache.getSearchService().removeByTags(tags, TagSearchOptions.ByAnyTag);
+ System.out.println("Removed Items by Tags \"Technology\" and \"Reading\"\n");
+
+ System.out.println("Sample completed successfully.");
+ cache.close();
+ }
+
+ private static void printProductDetails(Collection items) {
+ if (items != null && !items.isEmpty()) {
+ System.out.println("ProductID, Name, Price, Category");
+ for (Product product : items) {
+ System.out.println("- " + product.getProductID() + ", " + product.getName() + ", $" + product.getPrice() + ", " + product.getCategory());
+ }
+ } else {
+ System.out.println("No items found...");
+ }
+ System.out.println();
+ }
+}
+
+// Sample class for Product
+class Product implements Serializable {
+ private int productID;
+ private String name;
+ private int price;
+ private String category;
+
+ public Product(int productID, String name, int price, String category) {
+ this.productID = productID;
+ this.name = name;
+ this.price = price;
+ this.category = category;
+ }
+
+ public int getProductID() { return productID; }
+ public String getName() { return name; }
+ public int getPrice() { return price; }
+ public String getCategory() { return category; }
+}
diff --git a/playground/java/HibernateCaching/Code/pom.xml b/playground/java/HibernateCaching/Code/pom.xml
new file mode 100644
index 0000000..6f67ae1
--- /dev/null
+++ b/playground/java/HibernateCaching/Code/pom.xml
@@ -0,0 +1,119 @@
+
+
+ 4.0.0
+
+ com.alachisoft.ncache.samples
+ HibernateCaching
+ 5.3.3
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+ com.alachisoft.ncache
+ ncache-hibernate
+ 5.3.3
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ 4.0.0
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.20.0
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.20.0
+
+
+ org.hibernate.orm
+ hibernate-core
+ 6.3.1.Final
+
+
+ org.hibernate.validator
+ hibernate-validator
+ 8.0.1.Final
+
+
+ org.glassfish
+ jakarta.el
+ 4.0.2
+
+
+ org.hibernate.orm
+ hibernate-jpamodelgen
+ 6.3.0.Final
+ provided
+
+
+ com.h2database
+ h2
+ 2.1.214
+ runtime
+
+
+ com.alachisoft.ncache
+ ncache-client
+ 5.3.2
+
+
+ org.antlr
+ antlr4-runtime
+ 4.10.1
+
+
+
+
+ central
+ https://repo.maven.apache.org/maven2
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/HibernateCaching/Code/src/main/java/com/alachisoft/ncache/samples/HibernateCaching.java b/playground/java/HibernateCaching/Code/src/main/java/com/alachisoft/ncache/samples/HibernateCaching.java
new file mode 100644
index 0000000..fdb442b
--- /dev/null
+++ b/playground/java/HibernateCaching/Code/src/main/java/com/alachisoft/ncache/samples/HibernateCaching.java
@@ -0,0 +1,153 @@
+package com.alachisoft.ncache.samples;
+
+
+import jakarta.persistence.Column;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.service.ServiceRegistry;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+// Use NCache integration with Hibernate to seamlessly cache query results in an L2 cache.
+// Next time, Hibernate fetches these objects from the cache and saves an expensive database trip.
+// We're using an H2 in-memory database that goes away when the process ends.
+
+public class HibernateCaching {
+
+ public static void main(String[] args) {
+
+ System.out.println("Sample showing Hibernate caching with NCache to save expensive database trips.\n");
+ Logger.getLogger("org.hibernate").setLevel(Level.OFF);
+
+ // Configure Hibernate properties programmatically
+ Properties hibernateProperties = new Properties();
+ hibernateProperties.put("hibernate.connection.driver_class", "org.h2.Driver");
+ hibernateProperties.put("hibernate.connection.url", "jdbc:h2:mem:testdb");
+ hibernateProperties.put("hibernate.show_sql", "false");
+ hibernateProperties.put("hibernate.hbm2ddl.auto", "create-drop");
+ hibernateProperties.put("hibernate.cache.use_query_cache", "true");
+ hibernateProperties.put("hibernate.cache.use_second_level_cache", "true");
+ hibernateProperties.put("hibernate.cache.region.factory_class", "com.alachisoft.ncache.NCacheRegionFactory");
+ hibernateProperties.put("cache-name", args[0]);
+ hibernateProperties.put("ncache.application_id", "myapp");
+
+ // Set other Hibernate properties as needed
+ Configuration configuration = new Configuration()
+ .setProperties(hibernateProperties).addAnnotatedClass(Product.class);
+
+ // Build the ServiceRegistry
+ ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
+ .applySettings(configuration.getProperties()).build();
+
+ // Build the SessionFactory
+ SessionFactory factory = configuration.buildSessionFactory(serviceRegistry);
+
+ // Create a List of Product objects
+ ArrayList products = (ArrayList) getProducts();
+
+ // Open a new Hibernate session to save products to the database. This also caches it
+ try (Session session = factory.openSession()) {
+ Transaction transaction = session.beginTransaction();
+ // save() method saves products to the database and caches it too
+ System.out.println("ProductID, Name, Price, Category");
+ for (Product product : products) {
+ System.out.println("- " + product.getProductID() + ", " + product.getName() + ", " + product.getPrice() + ", " + product.getCategory());
+ session.save(product);
+ }
+ transaction.commit();
+ System.out.println();
+ }
+
+ // Now open a new session to fetch products from the DB.
+ // But, these products are actually fetched from the cache
+ try (Session session = factory.openSession()) {
+ List productList = (List) session.createQuery("from Product").list();
+ if (productList != null) {
+ System.out.println("Found and retrieved all product from the cache...");
+ printProductDetails(productList);
+ }
+ }
+ System.out.println("Sample completed successfully.");
+ System.exit(0);
+ }
+
+ // Helper method to print product details.
+ private static void printProductDetails(Collection items) {
+ System.out.println("ProductID, Name, Price, Category");
+ if (items != null && !items.isEmpty()) {
+ for (Product product : items) {
+ System.out.println("- " + product.getProductID() + ", " + product.getName() + ", " + product.getPrice() + ", " + product.getCategory());
+ }
+ } else {
+ System.out.println("No items found...");
+ }
+ System.out.println();
+ }
+
+ // Helper method to create a list of Product objects.
+ private static List getProducts()
+ {
+ ArrayList products = new ArrayList<>();
+ products.add(new Product(14001, "Laptop", 2000, "Electronics"));
+ products.add(new Product(14002, "Kindle", 1000, "Electronics"));
+ products.add(new Product(14003, "Book", 100, "Stationery"));
+ products.add(new Product(14004, "Smart Phone", 1000, "Electronics"));
+ products.add(new Product(14005, "Mobile Phone", 200, "Electronics"));
+ return products;
+ }
+}
+
+// Sample class for Product
+@jakarta.persistence.Entity
+@jakarta.persistence.Cacheable
+@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "CustomersCache")
+class Product implements Serializable {
+ @jakarta.persistence.Id
+ private int productID;
+ @jakarta.persistence.Column
+ private String name;
+ @jakarta.persistence.Column
+ private double price;
+ @Column
+ private String category;
+
+ public Product() {
+ }
+
+ public Product(int productID, String name, double price, String category) {
+ this.productID = productID;
+ this.name = name;
+ this.price = price;
+ this.category = category;
+ }
+
+ public int getProductID() { return productID; }
+ public String getName() { return name; }
+ public double getPrice() { return price; }
+ public String getCategory() { return category; }
+
+}
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
diff --git a/playground/java/HibernateCaching/NCacheHibernate.xml b/playground/java/HibernateCaching/NCacheHibernate.xml
new file mode 100644
index 0000000..9ce7010
--- /dev/null
+++ b/playground/java/HibernateCaching/NCacheHibernate.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/playground/java/PubSubMessaging/Code/pom.xml b/playground/java/PubSubMessaging/Code/pom.xml
new file mode 100644
index 0000000..d65a46a
--- /dev/null
+++ b/playground/java/PubSubMessaging/Code/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+
+
+ com.alachisoft.ncache.samples
+ PubSubMessaging
+ 5.3.0
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.alachisoft.ncache
+ ncache-client
+ ${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/PubSubMessaging/Code/src/main/java/com/alachisoft/ncache/samples/PubSubMessaging.java b/playground/java/PubSubMessaging/Code/src/main/java/com/alachisoft/ncache/samples/PubSubMessaging.java
new file mode 100644
index 0000000..1521a03
--- /dev/null
+++ b/playground/java/PubSubMessaging/Code/src/main/java/com/alachisoft/ncache/samples/PubSubMessaging.java
@@ -0,0 +1,164 @@
+package com.alachisoft.ncache.samples;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import com.alachisoft.ncache.client.*;
+import com.alachisoft.ncache.client.services.MessagingService;
+import com.alachisoft.ncache.runtime.caching.*;
+import com.alachisoft.ncache.runtime.caching.messaging.MessageReceivedListener;
+
+// Use NCache Pub/Sub Messaging in this sample. In NCache, you can create multiple Topics
+// and against each topic create multiple publishers and subscribers. In this sample,
+// 2 parallel Async publisher tasks publish on the same topic and 2 subscribers receive
+// messages from this topic. All messages use DeliveryOption. Any so only one subscriber
+// gets each message. DeliveryOption.All is available but not used.
+
+public class PubSubMessaging {
+ static String topicName = "ORDERS";
+ static final Object lock = new Object();
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("Sample showing NCache Pub/Sub Messaging for reliable real-time messaging between publishers and subscribers.\n");
+
+ String cacheName = args[0];
+
+ System.out.println("Connecting to cache: " + cacheName);
+ // Connect to the cache and return a cache handle
+ Cache cache = CacheManager.getCache(cacheName);
+ System.out.println("Connected to Cache successfully: " + cacheName + "\n");
+
+ System.out.println("Create a Topic " + topicName + " ...\n");
+
+ // Create a Topic in NCache.
+ MessagingService messagingService = cache.getMessagingService();
+ Topic topic = messagingService.createTopic(topicName);
+
+ System.out.println("Register 2 subscribers for Topic " + topicName + "\n");
+
+ // Register subscribers to this Topic
+ MessageReceivedListener subscriptionListener1 = new MessageReceivedListener() {
+ @Override
+ public void onMessageReceived(Object o, MessageEventArgs messageEventArgs) {
+ messageReceivedSubscription1(messageEventArgs.getMessage());
+ }
+ };
+ MessageReceivedListener subscriptionListener2 = new MessageReceivedListener() {
+ @Override
+ public void onMessageReceived(Object o, MessageEventArgs messageEventArgs) {
+ messageReceivedSubscription2(messageEventArgs.getMessage());
+ }
+ };
+ TopicSubscription subscription1 = topic.createSubscription(subscriptionListener1);
+ TopicSubscription subscription2 = topic.createSubscription(subscriptionListener2);
+
+ // Create a thread pool for publishers
+ ExecutorService publisherThreadPool = Executors.newFixedThreadPool(2);
+
+ // Create first asynchronous publisher task to publish 2 messages
+ publisherThreadPool.submit(() -> {
+ try {
+ Message message1 = new Message(
+ new Order(17348, "Vins et alcools Chevalier", LocalDate.parse("1997-07-04"), "Federal Shipping"));
+
+ Message message2 = new Message(
+ new Order(17350, "Hanari Carnes", LocalDate.parse("1997-07-07"), "United Package"));
+
+ printMessage(message1, "Publisher 1", null);
+ // "Any" means that only one subscriber will receive this message
+ // Another option is "All" where all subscribers receive the message
+ topic.publish(message1, DeliveryOption.Any);
+
+ // Wait for 1 second before publishing again
+ Thread.sleep(1000);
+ printMessage(message2, "Publisher 1", null);
+
+ topic.publish(message2, DeliveryOption.Any);
+ } catch (Exception ex) {
+ }
+ });
+
+ // Create second asynchronous publisher task to publish 2 messages
+ publisherThreadPool.submit(() -> {
+ try {
+ Message message1 = new Message(
+ new Order(17349, "Toms Spezialitäten", LocalDate.parse("1997-07-05"), "Speedy Express"));
+
+ Message message2 = new Message(
+ new Order(17351, "Victuailles en stock", LocalDate.parse("1997-07-08"), "Speedy Express"));
+
+ printMessage(message1, "Publisher 2", null);
+
+ // "Any" means that only one subscriber will receive this message
+ // Another option is "All" where all subscribers receive the message
+ topic.publish(message1, DeliveryOption.Any);
+
+ // Wait for 1 second before publishing again
+ Thread.sleep(1000);
+ printMessage(message2, "Publisher 2", null);
+
+ topic.publish(message2, DeliveryOption.Any);
+ } catch (Exception ex) {
+ }
+ });
+
+ // Wait for 5 seconds
+ Thread.sleep(5000);
+
+ // Unsubscribe subscribers
+ subscription1.unSubscribe();
+ subscription2.unSubscribe();
+
+ // Shut down the thread pool
+ publisherThreadPool.shutdown();
+
+ topic.close();
+ System.out.println("Sample completed successfully.");
+ cache.close();
+ }
+
+ private static void messageReceivedSubscription1(Message message) {
+ printMessage(message, null, "Subscriber 1");
+ }
+
+ private static void messageReceivedSubscription2(Message message) {
+ printMessage(message, null, "Subscriber 2");
+ }
+
+ static void printMessage(Message message, String sender, String receiver) {
+ Order order = (Order) message.getPayload();
+
+ synchronized (lock) {
+ if (sender != null && !sender.isEmpty()) {
+ System.out.println(sender + " publishes a message for Topic " + topicName + " ...");
+ } else if (receiver != null && !receiver.isEmpty()) {
+ System.out.println(receiver + " receives message ...");
+ }
+
+ System.out.println("OrderID, Customer, Order Date, Ship Via");
+ System.out.println("- " + order.getOrderID() + ", " + order.getCustomer() + ", "
+ + order.getOrderDate().toString() + ", " + order.getShipVia() + " \n");
+ }
+ }
+}
+// Sample class for Order
+class Order implements Serializable {
+ private int orderID;
+ private String customer;
+ private LocalDate orderDate;
+ private String shipVia;
+
+ public Order(int orderID, String customer, LocalDate orderDate, String shipVia) {
+ this.orderID = orderID;
+ this.customer = customer;
+ this.orderDate = orderDate;
+ this.shipVia = shipVia;
+ }
+
+ public int getOrderID() { return orderID; }
+ public String getCustomer() { return customer; }
+ public LocalDate getOrderDate() { return orderDate; }
+ public String getShipVia() { return shipVia; }
+}
\ No newline at end of file
diff --git a/playground/java/SpringDataCaching/Code/pom.xml b/playground/java/SpringDataCaching/Code/pom.xml
new file mode 100644
index 0000000..226cf2d
--- /dev/null
+++ b/playground/java/SpringDataCaching/Code/pom.xml
@@ -0,0 +1,92 @@
+
+
+ 4.0.0
+
+
+ com.alachisoft.ncache.samples
+ SpringDataCaching
+ 5.3.0
+
+
+ 11
+ 11
+
+
+
+ org.springframework
+ spring-context
+ 6.0.11
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ 3.1.3
+
+
+ com.alachisoft.ncache
+ ncache-spring
+ 5.3.0
+
+
+ com.h2database
+ h2
+ 2.2.222
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+ 3.1.3
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ com.alachisoft.ncache.samples.SpringResultSetCaching
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
+
diff --git a/playground/java/SpringDataCaching/Code/src/main/java/com/alachisoft/ncache/samples/SpringDataCaching.java b/playground/java/SpringDataCaching/Code/src/main/java/com/alachisoft/ncache/samples/SpringDataCaching.java
new file mode 100644
index 0000000..5b4c648
--- /dev/null
+++ b/playground/java/SpringDataCaching/Code/src/main/java/com/alachisoft/ncache/samples/SpringDataCaching.java
@@ -0,0 +1,198 @@
+package com.alachisoft.ncache.samples;
+
+import com.alachisoft.ncache.spring.NCacheCacheManager;
+import com.alachisoft.ncache.spring.configuration.SpringConfigurationManager;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.*;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Repository;
+import org.springframework.stereotype.Service;
+
+import java.io.Serializable;
+import java.nio.file.Path;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+// Use NCache integration with Spring to seamlessly cache objects. Next time, Spring fetches these
+// objects from the cache and saves an expensive database trip. We're using an H2 in-memory database
+// that goes away when the process ends.
+
+@SpringBootApplication
+@EnableCaching
+public class SpringDataCaching {
+ public static void main(String[] args) {
+
+ System.out.println("Sample showing Spring caching with NCache to save expensive database trips.\n");
+
+ // Running spring application
+ ConfigurableApplicationContext context = SpringApplication.run(SpringDataCaching.class, args);
+
+ // Get a Spring Service to save objects in the DB. This also caches them with 5min absolute (TTL) expiration.
+ BookService service = context.getBean(BookService.class);
+ service.save(new Book(18001, "The Second Machine Age", "Erik Brynjolfsson, Andrew McAfee", new Date(2014, 0, 20)));
+ service.save(new Book(18002, "Harry Potter and the Prisoner of Azkaban", "J.K. Rowling", new Date(1999, 6, 8)));
+ service.save(new Book(18003, "Cloud Computing | Methodology, Systems, and Applications", "Lizhe Wang, Rajiv Ranjan", new Date(2011, 9, 3)));
+ service.save(new Book(18004, "The Alchemist", "Paulo Coelho", new Date(19993, 0, 1)));
+
+ // Print all saved books details
+ printBooks(service.listAll());
+
+ System.out.println("\nFinding book by isbn# ...");
+
+ // Use Spring Service to get a book from the DB. It actually comes from the cache
+ Book foundBook = service.findBookByIsbn(18001);
+ printBookDetails(foundBook);
+
+ // Use Spring Service to save "updated" book to the DB. It updates the cache too
+ System.out.println("\nUpdating the book author in DB...");
+ foundBook.setAuthor("New Author");
+ Book UpdatedBook = service.update(foundBook);
+
+ System.out.println("\nUpdated book info...");
+ printBookDetails(UpdatedBook);
+
+
+ System.out.println("\n" + "Sample completed successfully.");
+ context.close();
+ System.exit(0);
+ }
+
+ // Helper method to print book details.
+ private static void printBooks(List books) {
+ System.out.println("Total Books: " + books.size());
+
+ System.out.println("BookID, ISBN, Title, Author");
+ for (Book book : books) {
+ System.out.println("- " + book.getId() + ", " + book.getISBN() + ", " + book.getTitle() + ", " + book.getAuthor());
+ }
+ }
+
+ // Helper method to print book details.
+ private static void printBookDetails(Book book) {
+ System.out.println("BookID, ISBN, Title, Author");
+ System.out.println("- " + book.getId() + ", " + book.getISBN() + ", " + book.getTitle() + ", " + book.getAuthor());
+ }
+}
+
+// Class to get connected with cache.
+@Configuration
+class CachingConfiguration {
+ @Autowired
+ private ApplicationArguments applicationArguments;
+ @Bean
+ public CacheManager cacheManager() {
+ String[] args = applicationArguments.getSourceArgs();
+ String resource = Path.of(System.getenv("NCHOME"), "config/ncache-spring.xml").toString();
+
+ SpringConfigurationManager springConfigurationManager = new SpringConfigurationManager();
+ springConfigurationManager.setConfigFile(resource);
+
+ Properties properties = new Properties();
+ properties.setProperty("ncacheid-instance", args[0]);
+
+ NCacheCacheManager cacheManager = new NCacheCacheManager();
+ cacheManager.setSpringConfigurationManager(springConfigurationManager);
+
+ return cacheManager;
+ }
+}
+
+//Helper class to perform CRUD operations.
+@Service
+class BookService {
+ @Autowired
+ private BookRepository repo;
+
+ public List listAll() {
+ return repo.findAll();
+ }
+
+ @CachePut(value = "books", key = "#book.getISBN()")
+ public Book save(Book book) { return repo.save(book); }
+
+ @CachePut(value = "books", key = "#book.getISBN()")
+ public Book update(Book book) { return repo.save(book); }
+
+ @Cacheable(value = "books", key = "#id")
+ public Book get(int id) {
+ return repo.findById(id);
+ }
+
+ @Cacheable(value = "books", key = "#isbn")
+ public Book findBookByIsbn(long isbn) {
+ return repo.findBookByIsbn(isbn);
+ }
+
+ @CacheEvict(value = "books", allEntries = true)
+ public void delete(int id) {
+ repo.deleteById(id);
+ }
+}
+
+@Repository
+interface BookRepository extends CrudRepository {
+ Book findById(int id);
+ @NonNull
+ List findAll();
+ void deleteById(int id);
+ Book findBookByIsbn(long isbn);
+}
+
+// Book class to store book details.
+@Entity
+class Book implements Serializable {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Integer id;
+ private long isbn;
+ private String title;
+ private String author;
+ private Date publishedDate;
+
+ public Book() {
+ }
+
+ public Book(long isbn, String title,
+ String author, Date publishedDate) {
+ this.isbn = isbn;
+ this.title = title;
+ this.author = author;
+ this.publishedDate = publishedDate;
+ }
+
+ public void setAuthor(String author) { this.author = author; }
+ public long getISBN() { return isbn; }
+ public void setId(Integer id) { this.id = id; }
+ public void setISBN(long isbn) { this.isbn = isbn; }
+ public Integer getId() { return id; }
+ public String getTitle() { return title; }
+ public void setTitle(String title) { this.title = title; }
+ public String getAuthor() { return author; }
+ public Date getPublishedDate() { return publishedDate; }
+ public void setPublishedDate(Date publishedDate) { this.publishedDate = publishedDate; }
+}
+
+//ncache-spring.xml:
+
+//
+//
+//
+//
+//
\ No newline at end of file
diff --git a/playground/java/SpringDataCaching/Code/src/main/resources/application.properties b/playground/java/SpringDataCaching/Code/src/main/resources/application.properties
new file mode 100644
index 0000000..d8a6c94
--- /dev/null
+++ b/playground/java/SpringDataCaching/Code/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.datasource.url=jdbc:h2:mem:testdb
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=
+spring.jpa.hibernate.ddl-auto=update
+logging.level.root=OFF
+#spring.main.banner-mode=off
\ No newline at end of file
diff --git a/playground/java/SpringDataCaching/Code/src/main/resources/beans.xml b/playground/java/SpringDataCaching/Code/src/main/resources/beans.xml
new file mode 100644
index 0000000..c03a565
--- /dev/null
+++ b/playground/java/SpringDataCaching/Code/src/main/resources/beans.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/SpringDataCaching/Code/src/main/resources/ncache-spring.xml b/playground/java/SpringDataCaching/Code/src/main/resources/ncache-spring.xml
new file mode 100644
index 0000000..954ffab
--- /dev/null
+++ b/playground/java/SpringDataCaching/Code/src/main/resources/ncache-spring.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/playground/java/SqlQueryCacheLookup/Code/pom.xml b/playground/java/SqlQueryCacheLookup/Code/pom.xml
new file mode 100644
index 0000000..db6c11a
--- /dev/null
+++ b/playground/java/SqlQueryCacheLookup/Code/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+
+
+ com.alachisoft.ncache.samples
+ SqlQueryCacheLookup
+ 5.3.0
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.alachisoft.ncache
+ ncache-client
+ ${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/../../../libs
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.1
+
+ bin/
+
+
+ true
+ ../../../libs/
+ ${project.groupId}.${project.artifactId}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/playground/java/SqlQueryCacheLookup/Code/src/main/java/com/alachisoft/ncache/samples/SqlQueryCacheLookup.java b/playground/java/SqlQueryCacheLookup/Code/src/main/java/com/alachisoft/ncache/samples/SqlQueryCacheLookup.java
new file mode 100644
index 0000000..c52e499
--- /dev/null
+++ b/playground/java/SqlQueryCacheLookup/Code/src/main/java/com/alachisoft/ncache/samples/SqlQueryCacheLookup.java
@@ -0,0 +1,192 @@
+package com.alachisoft.ncache.samples;
+
+import java.math.BigDecimal;
+import java.io.Serializable;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import com.alachisoft.ncache.client.*;
+import com.alachisoft.ncache.runtime.caching.Tag;
+import com.alachisoft.ncache.runtime.exceptions.CacheException;
+import com.alachisoft.ncache.runtime.exceptions.OperationFailedException;
+import com.alachisoft.ncache.client.QueryIndexable;
+
+// Use SQL to query for cached data in NCache based on object attributes and Tags instead of just keys.
+// NCache SQL query requires indexes to be created on all objects being searched. One way is
+// thru cache configuration. Second is through code using "Custom Attributes" to annotate object fields
+// and create index on them automatically when they're added to the cache.
+// In this sample, we're using "Custom Attributes" to create index on Product object.
+
+public class SqlQueryCacheLookup {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println("Sample showing SQL queries to find data in NCache based on object attributes instead of keys.\n");
+
+ String cacheName = args[0];
+
+ System.out.println("Connecting to cache: " + cacheName);
+ // Connect to the cache and return a cache handle
+ Cache cache = CacheManager.getCache(cacheName);
+ System.out.println("Connected to Cache successfully: " + cacheName + "\n");
+
+ // Adds all the products to the cache. This automatically creates indexes on various
+ // attributes of Product object by using "Custom Attributes".
+ addSampleData(cache);
+
+ System.out.println("Find products with Category IN (\"Electronics\", \"Stationery\") AND Price < $2000");
+
+ // $VALUE$ keyword means the entire object instead of individual attributes that are also possible
+ String sql = "SELECT $VALUE$ FROM com.alachisoft.ncache.samples.Product WHERE category IN (?, ?) AND price < ?";
+
+ QueryCommand sqlCommand = new QueryCommand(sql);
+
+ List catParamList = new ArrayList<>(Arrays.asList(("Electronics"), ("Stationery")));
+ sqlCommand.getParameters().put("category", catParamList);
+ sqlCommand.getParameters().put("price", 2000);
+
+ // ExecuteReader returns ICacheReader with the query resultset
+ CacheReader resultSet = cache.getSearchService().executeReader(sqlCommand);
+ List fetchedProducts = new ArrayList<>();
+ if (resultSet.getFieldCount() > 0) {
+ while (resultSet.read()) {
+ // getValue() with $VALUE$ keyword returns the entire object instead of just one column
+ fetchedProducts.add(resultSet.getValue("$VALUE$", Product.class));
+ }
+ }
+ printProducts(fetchedProducts);
+
+ System.out.println("Find all \"phone\" products (using LIKE operator) AND (Tag = \"Technology\" OR Tag = \"Gadgets\")");
+ sql = "SELECT $VALUE$ FROM com.alachisoft.ncache.samples.Product WHERE name LIKE ? AND ($Tag$ = ? OR $Tag$ = ?)";
+
+ List tagList = new ArrayList<>(Arrays.asList(("Technology"), ("Gadgets")));
+
+ sqlCommand = new QueryCommand(sql);
+ sqlCommand.getParameters().put("name", "*Phone*");
+ sqlCommand.getParameters().put("$Tag$", tagList);
+
+ resultSet = cache.getSearchService().executeReader(sqlCommand);
+ fetchedProducts.clear();
+ if (resultSet.getFieldCount() > 0) {
+ while (resultSet.read()) {
+ // getValue() with $VALUE$ keyword returns the entire object instead of just one column
+ fetchedProducts.add(resultSet.getValue("$VALUE$", Product.class));
+ }
+ }
+ printProducts(fetchedProducts);
+
+ System.out.println("GROUP BY query: Get a count of product by category with Price < $3000");
+ sql = "SELECT category, COUNT(*) FROM com.alachisoft.ncache.samples.Product WHERE price < ? GROUP BY category";
+
+ sqlCommand = new QueryCommand(sql);
+
+ sqlCommand.getParameters().put("price", 3000);
+
+ CacheReader groupByResultSet = cache.getSearchService().executeReader(sqlCommand);
+ System.out.println("Category, Count");
+ if (groupByResultSet.getFieldCount() > 0) {
+ while (groupByResultSet.read()) {
+ String category = groupByResultSet.getValue(0, String.class);
+ BigDecimal count = groupByResultSet.getValue(1, BigDecimal.class);
+ System.out.println("- " + category + ", " + count);
+ }
+ }
+
+ System.out.println("\nDelete Items by Tags \"Technology\" and \"Reading\"");
+ sql = "DELETE FROM com.alachisoft.ncache.samples.Product WHERE $Tag$ IN (?, ?)";
+ sqlCommand = new QueryCommand(sql);
+
+ List removeTagsList = new ArrayList<>(Arrays.asList(("Technology"), ("Reading")));
+ sqlCommand.getParameters().put("$Tag$", removeTagsList);
+
+ int itemsRemoved = cache.getSearchService().executeNonQuery(sqlCommand);
+ System.out.println(itemsRemoved + " items removed from the cache.\n");
+
+ System.out.println("Sample completed successfully.");
+ cache.close();
+ }
+
+ static void addSampleData(Cache cache) throws CacheException {
+ System.out.println("Adding products to the cache with tags...");
+
+ Product laptop = new Product(13001, "Laptop", 2000, "Electronics");
+ Product kindle = new Product(13002, "Kindle", 1000, "Electronics");
+ Product book = new Product(13003, "Book", 100, "Stationery");
+ Product smartPhone = new Product(13004, "Smart Phone", 1000, "Electronics");
+ Product mobilePhone = new Product(13005, "Mobile Phone", 200, "Electronics");
+
+ CacheItem laptopCacheItem = new CacheItem(laptop);
+ List laptopTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Gadgets")));
+ laptopCacheItem.setTags(laptopTags);
+
+ CacheItem kindleCacheItem = new CacheItem(kindle);
+ List kindleTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Reading")));
+ kindleCacheItem.setTags(kindleTags);
+
+ CacheItem bookCacheItem = new CacheItem(book);
+ List bookTags = new ArrayList<>(Arrays.asList(new Tag("Education"), new Tag("Reading")));
+ bookCacheItem.setTags(bookTags);
+
+ CacheItem smartPhoneCacheItem = new CacheItem(smartPhone);
+ List smartPhoneTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Communication")));
+ smartPhoneCacheItem.setTags(smartPhoneTags);
+
+ CacheItem mobilePhoneCacheItem = new CacheItem(mobilePhone);
+ List mobilePhoneTags = new ArrayList<>(Arrays.asList(new Tag("Technology"), new Tag("Communication")));
+ mobilePhoneCacheItem.setTags(mobilePhoneTags);
+
+ Map products = new HashMap<>();
+ products.put("13001", laptopCacheItem);
+ products.put("13002", kindleCacheItem);
+ products.put("13003", bookCacheItem);
+ products.put("13004", smartPhoneCacheItem);
+ products.put("13005", mobilePhoneCacheItem);
+
+ // Adds all the products to the cache. This automatically creates indexes on various
+ // attributes of Product object by using "Custom Attributes".
+ for (Map.Entry product : products.entrySet()) {
+ cache.insert(product.getKey(), product.getValue());
+ }
+
+ List productValues = products.values().stream()
+ .map(cacheItem -> {
+ try {
+ return (Product) cacheItem.getValue(Product.class);
+ } catch (OperationFailedException e) {
+ throw new RuntimeException(e);
+ }
+ })
+ .collect(Collectors.toList());
+ printProducts(productValues);
+ }
+
+ static void printProducts(List products) {
+ System.out.println("ProductID, Name, Price, Category");
+ for (Product product : products) {
+ System.out.println("- " + product.getProductID() + ", " + product.getName() + ", $" + product.getPrice() + ", " + product.getCategory());
+ }
+ System.out.println();
+ }
+}
+
+// Sample class for Product
+@QueryIndexable
+class Product implements Serializable {
+ private int productID;
+ private String name;
+ private int price;
+ private String category;
+
+ public Product(int productID, String name, int price, String category) {
+ this.productID = productID;
+ this.name = name;
+ this.price = price;
+ this.category = category;
+ }
+
+ public int getProductID() { return productID; }
+ public String getName() { return name; }
+ public double getPrice() { return price; }
+ public void setPrice(int price) { this.price = price; }
+ public String getCategory() { return category; }
+}
\ No newline at end of file