{"id":9139,"date":"2024-03-19T13:39:10","date_gmt":"2024-03-19T04:39:10","guid":{"rendered":"https:\/\/www.auctionpro.co.kr\/?p=9139"},"modified":"2024-04-19T10:03:09","modified_gmt":"2024-04-19T01:03:09","slug":"netcore6-0-memory-cache-mysql-mssql","status":"publish","type":"post","link":"https:\/\/www.auctionpro.co.kr\/?p=9139","title":{"rendered":"NetCore6.0 Memory Cache (MySQL, MsSQL) \uc120\ud0dd\uac00\ub2a5"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Remark : DB \uc27d\uac8c \uc138\ud305,  ICacheGetSet \uc73c\ub85c \uac04\ub2e8\ud558\uac8c \uad6c\uc131 \ud558\uae30<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>using InMemoryCacheCore.App_Data.MsSQL \ub610\ub294 .MySQL \uc120\ud0dd<\/li>\n\n\n\n<li>V11, V12, V13 \ubc84\uc804\uad00\ub9ac \ud558\uae30<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">UML<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"629\" src=\"https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-4-1024x629.png\" alt=\"\" class=\"wp-image-9136\" srcset=\"https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-4-1024x629.png 1024w, https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-4-300x184.png 300w, https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-4-768x472.png 768w, https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-4.png 1128w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Files<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-5.png\"><img loading=\"lazy\" decoding=\"async\" width=\"359\" height=\"479\" src=\"https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-5.png\" alt=\"\" class=\"wp-image-9137\" srcset=\"https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-5.png 359w, https:\/\/www.auctionpro.co.kr\/wp-content\/uploads\/2024\/03\/image-5-225x300.png 225w\" sizes=\"auto, (max-width: 359px) 100vw, 359px\" \/><\/a><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">MsSQL -&gt; AirlineDBContext.cs<\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true \" title=\"AirlineDBContext \">using Microsoft.EntityFrameworkCore;\nusing InMemoryCacheCore.Models;\n\nnamespace InMemoryCacheCore.App_Data.MsSQL\n{\n    public class AirlineDBContext : DbContext\n    {\n        static readonly string MySQLconnectionString = \"Server=SQLOLEDB.1;Password=XXXXXX;Persist Security Info=True;User ID=IDXXX;Initial Catalog=BasicCode;Data Source=XXX.XXX.XXX.XXX\";\n\n        public DbSet&lt;Code&gt;? AIRLINE { get; set; }\n\n        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n        {\n            optionsBuilder.UseSqlServer(MySQLconnectionString);\n        }\n    }\n}\n<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">MySQL -&gt; AirlineDBContext.cs<\/h3>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true \">using Microsoft.EntityFrameworkCore;\nusing InMemoryCacheCore.Models;\n\nnamespace InMemoryCacheCore.App_Data.MySQL\n{\n    public class AirlineDBContext : DbContext\n    {  \n        static readonly string connectionString = \"Server=XXX.XXX.XXX.XXX,3306;User ID=XXXX;Password=XXXXX;Database=BasicCode\";\n\n        public DbSet&lt;Code&gt;? AIRLINE { get; set; }\n\n        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n        {\n            optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));\n        }\n\n    }\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">AirlineController.cs<\/h2>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true \" title=\"AirlineController \">using InMemoryCacheCore.Services02.V13;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace InMemoryCacheCore.Controllers\n{\n    [Route(\"api\/[controller]\")]\n    [ApiController]\n    public class AirlineController : ControllerBase\n    {\n        private readonly ICacheGetSet _cacheGetSet;\n\n        private readonly string _cacheKey = \"_ACode\";\n\n        public AirlineController(ICacheGetSet cacheGetSet )\n        {\n            _cacheGetSet = cacheGetSet ?? throw new ArgumentNullException(nameof(cacheGetSet));\n        }\n\n        \/\/ GET: api\/&lt;ValuesController&gt;\n        [HttpGet]\n        public async Task&lt;IEnumerable&lt;Code&gt;&gt; Get()\n        {\n            try {\n                IEnumerable&lt;Code&gt;? codes = await _cacheGetSet.CacheGet(_cacheKey);\n                return codes;\n                }\n                catch {\n                    return Enumerable.Empty&lt;Code&gt;();\n                }\n        }\n\n    }\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">AirlineHttpClient.cs<\/h2>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true \" title=\"AirlineHttpClient \">using Microsoft.EntityFrameworkCore;\nusing InMemoryCacheCore.Models;\nusing InMemoryCacheCore.App_Data.MySQL;\n\nnamespace InMemoryCacheCore.Infrastructure\n{\n    public interface IHttpClient\n    {\n        Task&lt;IEnumerable&lt;Code&gt;&gt; Get();\n    }\n\n    public class AirlineHttpClient : IHttpClient\n    {\n        public async Task&lt;IEnumerable&lt;Code&gt;&gt; Get()\n        {\n            AirlineDBContext _context = new();\n\n            if (_context.AIRLINE != null)\n            {\n                var codesResponse = await _context.AIRLINE.ToListAsync();\n\n                return codesResponse;\n            }\n            else\n            {\n                \/\/throw new Exception(\"\");\n                return Array.Empty&lt;Code&gt;();\n            }\n        }\n    }\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">CacheProvider.cs<\/h2>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true \" title=\"CacheProvider \">using Microsoft.Extensions.Caching.Memory;\n\nnamespace InMemoryCacheCore.Infrastructure\n{\n    public interface ICacheProvider\n    {\n        T? GetFromCache&lt;T&gt;(string key) where T : class;\n        void SetCache&lt;T&gt;(string key, T value, MemoryCacheEntryOptions options) where T : class;\n        void ClearCache(string key);\n    }\n\n    public class CacheProvider : ICacheProvider\n    {\n        private readonly IMemoryCache _cache;\n\n        public CacheProvider(IMemoryCache cache)\n        {\n            _cache = cache;\n        }\n\n        public T? GetFromCache&lt;T&gt;(string key) where T : class\n        {\n            \/\/_cache.TryGetValue(key, out T cachedResponse);\n            \/\/return cachedResponse as T;\n            return _cache.Get&lt;T&gt;(key);\n        }\n\n        public void SetCache&lt;T&gt;(string key, T value, MemoryCacheEntryOptions options) where T : class\n        {\n            _cache.Set(key, value, options);\n        }\n\n        public void ClearCache(string key)\n        {\n            _cache.Remove(key);\n        }\n    }\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Airline.cs<\/h2>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true \">using System.ComponentModel.DataAnnotations;\n\nnamespace InMemoryCacheCore.Models\n{\n    public class Code\n    {\n        [Key]\n        [Display(Name = \"Airlinecode\")]\n        public string? Airlinecode { get; set; }\n\n        [Display(Name = \"Airline3code\")]\n        public string? Airline3code { get; set; } \/\/Can't convert VarChar to Int32\n\n        [Display(Name = \"Airlinekor\")]\n        public string? Airlinekor { get; set; }\n\n        [Display(Name = \"Airlineeng\")]\n        public string? Airlineeng { get; set; }\n    }\n}<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">CacheGetSet.cs<\/h2>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:vim decode:true \" title=\"CacheGetSet\">using InMemoryCacheCore.Models;\nusing Microsoft.Extensions.Caching.Memory;\nusing InMemoryCacheCore.Infrastructure;\n\nnamespace InMemoryCacheCore.Services02.V13\n{\n    public interface ICacheGetSet\n    {\n        Task&lt;IEnumerable&lt;Code&gt;&gt; CacheGet(string _cacheKey);\n    }\n\n    public class CacheGetSet : ICacheGetSet\n    {\n        private readonly ICacheProvider? _cacheProvider;\n        private readonly IHttpClient _httpClient;\n        private readonly ILogger&lt;CacheGetSet&gt; _logger;\n\n        private const int CacheTTLInSeconds = 100;\n        private readonly MemoryCacheEntryOptions cacheEntryOptions = new MemoryCacheEntryOptions()\n                    .SetSlidingExpiration(TimeSpan.FromSeconds(CacheTTLInSeconds));\n\n        private static readonly SemaphoreSlim GetUsersSemaphore = new(1, 1);\n\n        public CacheGetSet(ICacheProvider? cacheProvider, IHttpClient httpClient, ILogger&lt;CacheGetSet&gt; logger)\n        {\n            _cacheProvider = cacheProvider;\n            _httpClient = httpClient;\n            _logger = logger;\n        }\n\n        public async Task&lt;IEnumerable&lt;Code&gt;&gt; CacheGet(string _cacheKey)\n        {\n            try\n            {\n                IEnumerable&lt;Code&gt;? codes = _cacheProvider?.GetFromCache&lt;IEnumerable&lt;Code&gt;&gt;(_cacheKey);\n\n                if (codes == null || !codes.Any())\n                {\n                    codes = await _httpClient.Get();\n\n                    await GetUsersSemaphore.WaitAsync();\n                    _cacheProvider?.SetCache(_cacheKey, codes, cacheEntryOptions);\n                    GetUsersSemaphore.Release();\n                }\n\n                return codes;\n            }\n            catch (Exception ex)\n            {\n                _logger.LogError(ex, \"\uc815\ubcf4\ub97c \uac00\uc838\uc624\ub294 \ub3d9\uc548 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\");\n                \/\/ If you want to re-throw the exception, use \"throw;\" here.\n                return Enumerable.Empty&lt;Code&gt;();\n            }\n        }\n    }\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Program.cs<\/h2>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:c# decode:true \" title=\"Program.cs\">using InMemoryCacheCore.Infrastructure;\nusing InMemoryCacheCore.Services02.V13;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n\/\/ Add services to the container.\n\nbuilder.Services.AddControllers();\nbuilder.Services.AddEndpointsApiExplorer();\nbuilder.Services.AddSwaggerGen();\n\nbuilder.Services.AddHttpClient();\n\nbuilder.Services.AddSingleton&lt;ICacheProvider, CacheProvider&gt;(); \/\/infrastructure\nbuilder.Services.AddSingleton&lt;IHttpClient, AirlineHttpClient&gt;();   \/\/infrastructure\n\nbuilder.Services.AddScoped&lt;ICacheGetSet, CacheGetSet&gt;(); \/\/\ucd94\uac00\nbuilder.Services.AddMemoryCache();\n\nvar app = builder.Build();\n\n\/\/ Configure the HTTP request pipeline.\nif (app.Environment.IsDevelopment())\n{\n    app.UseSwagger();\n    app.UseSwaggerUI();\n}\n\napp.UseHttpsRedirection();\n\napp.UseAuthorization();\n\napp.MapControllers();\n\napp.Run();\n<\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>Remark : DB \uc27d\uac8c \uc138\ud305, ICacheGetSet \uc73c\ub85c \uac04\ub2e8\ud558\uac8c \uad6c\uc131 \ud558\uae30 UML Files MsSQL -&gt; AirlineDBContext.cs MySQL -&gt; AirlineDBContext.cs AirlineController.cs AirlineHttpClient.cs CacheProvider.cs Airline.cs CacheGetSet.cs Program.cs<\/p>\n<\/div>","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[237],"tags":[],"class_list":["post-9139","post","type-post","status-publish","format-standard","hentry","category-memory-cache"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/9139","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9139"}],"version-history":[{"count":0,"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/9139\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.auctionpro.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}