(MVC) MVC (2020)

How Linux Net Core 3.1 daemon (in VB.NET) can read/write data from/to ancient MS SQL 2005

1. Foundation of solution, external circumstances.

As start point I have huge DB in MS SQL 2005 with six terabyte data in Windows 2003.



In other side I need to communicate with modern Linux server by TSL 1.2.



How Is possible to solve this problem? There are some additional condition as secure communication with SQL server and finally I have so few time for this project therefore it will be VB program.

2. Solution architecture.

As a result of thinking I figure out a solution and realized it successfully.



3. Deploy NET CORE application as Linux daemon.

This is deployment process Deploy ASP.NET Core application from scratch (install and tune SSH/VNC/FTP/NGINX/Daemon). And below is my Net Core application, as you can see on library set this is WCF client



And this is a lot of scanning message from inet



4. WCF server (NET 4.0) in Windows 2003.

How I rich this result? As first step I write ordinary WCF service in NET Framework 4.0, because Windows 2003 not support more modern framework. I don't want describe this project, because it bored for me, its my liked type of projects, I done a lot of similar projects.



5. Create raw reference to WCF service in C# and without tuning.

So, what I done next? I take simple MS client for WCF service from VS2019. Unfortunately, MS Vilified Visual Basic (Why Microsoft vilified Visual Basic ?)and this client not support scaffolding to VB.



Than I must be create separate project with WCF reference in C#



6. Modify raw reference to add client config and compile it to dedicated library.

This project with WCF-client was be stupid, because IP-address if my server was be hard set in code. How can I deploy this project in server? Any IP address will be different in my development environment and production environment in server. Therefore I replace stupid Microsoft code to reading IP address from config file. This is line 727.



7. Include library with WCF reference to NET CORE VB project.

Than I simple set Wcf Client library as reference to may NET Core project.



This is definition of my WCF by definition of ServiceReference class.


   1:  Public Interface IAuWcf
   2:      Function CreateMD5(ByVal Input As String) As String
   3:      Function AuTest(Input As Integer) As String
   4:      Function AuAddTrace(Txt As String) As Integer
   5:      Function AuGetBlockIP() As ServiceReference1.RetBlockIP()
   6:      Function AuGetGrapHoperKey() As ServiceReference1.RetGraphHoperKey()
   7:      Function AuCheckIsUrlExist(Url As String) As Boolean
   8:      Function AuGetRoute(Url As String) As ServiceReference1.RetGraphHoperCache
   9:      Function AuAddRoute(Url As String, Route As String) As Long
  10:  End Interface

8. Create Authentication layer inside WCF communication to protect WCF server from rogue WCF client.

Than I created middleware - wrapper around WCF-function and protection, it will be communicate with my own library to identify client of WCF service - Protect WCF service by password


   1:  Imports ServiceReference1
   2:  Imports Newtonsoft.Json
   3:  Imports System.IO
   4:  Imports System.Text
   5:   
   6:  Public Class AuWcf
   7:      Implements IAuWcf
   8:   
   9:      Public WcfConfig As Dictionary(Of String, String)
  10:      Dim Wcf As ServiceReference1.Service1Client
  11:   
  12:      Public Sub New()
  13:          WcfConfig = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "WcfConfig.json")))
  14:          Wcf = New ServiceReference1.Service1Client
  15:      End Sub
  16:   
  17:      Public Function CreateMD5(ByVal Input As String) As String Implements IAuWcf.CreateMD5
  18:          Dim Sb = New StringBuilder()
  19:          Using Md5 As System.Security.Cryptography.MD5 = System.Security.Cryptography.MD5.Create()
  20:              Dim InputBytes As Byte() = System.Text.Encoding.ASCII.GetBytes(Input)
  21:              Dim HashBytes As Byte() = Md5.ComputeHash(InputBytes)
  22:              For I As Integer = 0 To HashBytes.Length - 1
  23:                  Sb.Append(HashBytes(I).ToString("X2"))
  24:              Next
  25:              Return Sb.ToString()
  26:          End Using
  27:      End Function
  28:   
  29:      'Stateless requests
  30:      Public Function AuTest(Input As Integer) As String Implements IAuWcf.AuTest
  31:          Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
  32:          Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
  33:          Dim TestRequest As New TestRequest(Bearer, Sign, Input)
  34:          Return Wcf.Test(TestRequest).TestResult
  35:      End Function
  36:   
  37:      Public Function AuAddTrace(Txt As String) As Integer Implements IAuWcf.AuAddTrace
  38:          Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
  39:          Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
  40:          Dim RQ1 As New AddTraceRequest(Bearer, Sign, Now, "Headers", Txt)
  41:          Return Wcf.AddTrace(RQ1).AddTraceResult
  42:      End Function
  43:   
  44:      Public Function AuGetBlockIP() As ServiceReference1.RetBlockIP() Implements IAuWcf.AuGetBlockIP
  45:          Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
  46:          Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
  47:          Dim RQ1 As New GetBlockIPRequest(Bearer, Sign)
  48:          Return Wcf.GetBlockIP(RQ1).GetBlockIPResult
  49:      End Function
  50:   
  51:      Public Function AuGetGrapHoperKey() As RetGraphHoperKey() Implements IAuWcf.AuGetGrapHoperKey
  52:          Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
  53:          Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
  54:          Dim RQ1 As New GetGrapHoperKeyRequest(Bearer, Sign)
  55:          Return Wcf.GetGrapHoperKey(RQ1).GetGrapHoperKeyResult
  56:      End Function
  57:   
  58:      Public Function AuCheckIsUrlExist(Url As String) As Boolean Implements IAuWcf.AuCheckIsUrlExist
  59:          Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
  60:          Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
  61:          Dim RQ1 As New CheckIsUrlExistRequest(Bearer, Sign, Url)
  62:          Return Wcf.CheckIsUrlExist(RQ1).CheckIsUrlExistResult
  63:      End Function
  64:   
  65:      Public Function AuGetRoute(Url As String) As RetGraphHoperCache Implements IAuWcf.AuGetRoute
  66:          Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
  67:          Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
  68:          Dim RQ1 As New GetRouteRequest(Bearer, Sign, Url)
  69:          Return Wcf.GetRoute(RQ1).GetRouteResult
  70:      End Function
  71:   
  72:      Public Function AuAddRoute(Url As String, Route As String) As Long Implements IAuWcf.AuAddRoute
  73:          Dim Bearer As String = Wcf.GetToken(New GetTokenRequest()).GetTokenResult
  74:          Dim Sign = CreateMD5(WcfConfig("Password") & Bearer)
  75:          Dim RQ1 As New AddRouteRequest(Bearer, Sign, Url, Route)
  76:          Return Wcf.AddRoute(RQ1).AddRouteResult
  77:      End Function
  78:  End Class

9. Text test WCF client configuration and raw WCF communication (MS Unit test).

As next step I have created MS Unit test for all my remote methods:



   1:  Imports System.Text
   2:  Imports Microsoft.VisualStudio.TestTools.UnitTesting
   3:  Imports Newtonsoft.Json
   4:   
   5:  Namespace MsWcfReferenceUnitTest1
   6:      <TestClass>
   7:      Public Class WcfTest1
   8:   
   9:          Private testContextInstance As TestContext
  10:          Public Property TestContext As TestContext
  11:              Get
  12:                  Return testContextInstance
  13:              End Get
  14:              Set(ByVal value As TestContext)
  15:                  testContextInstance = value
  16:              End Set
  17:          End Property
  18:   
  19:          Dim WcfServices As CoreLinux.AuWcf 'link to project with service references to WCF
  20:   
  21:          <TestInitialize>
  22:          Sub Start()
  23:              WcfServices = New CoreLinux.AuWcf
  24:              TestContext.WriteLine(JsonConvert.SerializeObject(WcfServices.WcfConfig, Formatting.Indented))
  25:          End Sub
  26:   
  27:          <TestMethod>
  28:          Sub AuTest()
  29:              Dim AuTestResult As String = WcfServices.AuTest(10)
  30:              Assert.AreEqual("10", AuTestResult)
  31:          End Sub
  32:   
  33:          <TestMethod>
  34:          Sub AuGetBlockIP()
  35:              Dim Str1 As New StringBuilder
  36:              Dim AuTestResult As ServiceReference1.RetBlockIP() = WcfServices.AuGetBlockIP()
  37:              AuTestResult.ToList.ForEach(Sub(X)
  38:                                              Str1.Append(X.I)
  39:                                              Str1.AppendLine(X.BlockNet)
  40:                                          End Sub)
  41:              TestContext.WriteLine(Str1.ToString)
  42:              Assert.IsTrue(True)
  43:          End Sub
  ...   

10. Inject WCF client with Authentication layer to Core DI container as Singleton service.

Than I have Injected dependency to ASP.MET Core DI container (in my case Singleton is enough).


  ...   
  19:  Public Class Startup
  ...   
  26:      Public Sub ConfigureServices(ByVal services As IServiceCollection)
  ...   
  35:          services.Add(New ServiceDescriptor(GetType(IAuWcf), New AuWcf()))
  36:          'or
  37:          services.AddSingleton(GetType(IAuWcf), New AuWcf())
  ...   

And than receive reference in controller



11. Test my WCF client with AU layer with Mock and Real log (Nunit).

Than I create full test my middleware for DI container with separate test of my middleware (my wrapper around WCF reference to hide security with comunnication with server) what I add to project as Singlton, and than test controller used my middlware (with Mock and Real log).


   1:  Imports NUnit.Framework
   2:  Imports Moq
   3:  Imports Microsoft.AspNetCore.Hosting
   4:  Imports Microsoft.Extensions.DependencyInjection
   5:  Imports Microsoft.Extensions.Hosting
   6:  Imports Microsoft.Extensions.Logging
   7:  Imports Microsoft.Extensions.Logging.Abstractions
   8:  Imports CoreLinux
   9:  Imports Newtonsoft.Json
  10:  Imports Microsoft.AspNetCore.Mvc
  11:   
  12:  Namespace CoreLinuxNUnitTest1
  13:   
  14:      Public Class Tests
  15:          Property CoreDIserviceCollection As IServiceCollection
  16:          Property CoreDIserviceProvider As ServiceProvider
  17:          Property MockLog As ILogger(Of CoreLinux.TestController)
  18:          Property RealLog As ILogger(Of CoreLinux.TestController)
  19:          Property AuWcf1 As AuWcf
  20:   
  21:          <SetUp>
  22:          Public Sub Setup()
  23:              CoreDIserviceCollection = New ServiceCollection()
  24:              CoreDIserviceProvider = CoreDIserviceCollection.AddLogging.BuildServiceProvider()
  25:          End Sub
  26:   
  27:          <Test>
  28:          Public Sub ShowServive()
  29:              Dim Str1 As New Text.StringBuilder
  30:              CoreDIserviceCollection.ToList.ForEach(Sub(ServiceDescriptor)
  31:                                                         Str1.Append(ServiceDescriptor.Lifetime.ToString & " : ")
  32:                                                         Str1.AppendLine(ServiceDescriptor.ServiceType.FullName)
  33:                                                     End Sub)
  34:              Assert.IsTrue(CoreDIserviceCollection.Count > 0)
  35:              TestContext.WriteLine("CoreDI builded " & CoreDIserviceCollection.Count & " services" & vbCrLf & Str1.ToString)
  36:              TestContext.WriteLine()
  37:          End Sub
  38:   
  39:          <Test>
  40:          Public Sub CreateMiddlwareInstance()
  41:              AuWcf1 = New AuWcf()
  42:              Assert.AreEqual(5, AuWcf1.WcfConfig.Count)
  43:              TestContext.WriteLine("WcfConfig" & vbCrLf & JsonConvert.SerializeObject(AuWcf1.WcfConfig, Formatting.Indented))
  44:              TestContext.WriteLine()
  45:          End Sub
  46:   
  47:          <Test>
  48:          Public Sub TestCoreSingletonServiceFactory()
  49:              ShowServive()
  50:              CreateMiddlwareInstance()
  51:              CoreDIserviceCollection.AddSingleton(GetType(IAuWcf), AuWcf1)
  52:              Dim Res As String = AuWcf1.AuTest(10)
  53:              Assert.AreEqual("10", Res)
  54:              ShowServive()
  55:          End Sub
  56:   
  57:          <Test>
  58:          Public Sub TestCoreControllerWithoutLog()
  59:              CreateMiddlwareInstance()
  60:              Dim Controller1 As New CoreLinux.TestController(AuWcf1)
  61:              Dim Response As IActionResult = Controller1.Index()
  62:              Dim Content As ContentResult = Response
  63:              TestContext.WriteLine(Content.Content)
  64:              Assert.AreEqual(Content.ContentType, "text/html")
  65:          End Sub
  66:   
  67:          <Test>
  68:          Public Sub AddMockLoggerWithOwnImpl()
  69:              ShowServive()
  70:              Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
  71:              MockLog = _Mock.Object
  72:              Dim MockLogger1 As MockLogger = New MockLogger()
  73:              MockLogger1.LogLevel = LogLevel.Information Or LogLevel.Error Or LogLevel.Warning Or LogLevel.Trace Or LogLevel.Debug Or LogLevel.Trace
  74:              CoreDIserviceCollection.AddSingleton(Of ILoggerFactory)(Function(s)
  75:                                                                          Dim loggerFactoryMock = New Mock(Of ILoggerFactory)()
  76:                                                                          loggerFactoryMock.Setup(Function(m) m.CreateLogger(It.IsAny(Of String)())).Returns(MockLogger1)
  77:                                                                          Return loggerFactoryMock.Object
  78:                                                                      End Function)
  79:   
  80:              MockLog.Log(LogLevel.Information, "MockLog")
  81:              ShowServive()
  82:          End Sub
  83:   
  84:          <Test>
  85:          Public Sub AddMockLoggerSimple()
  86:              Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
  87:              MockLog = _Mock.Object
  88:              CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), MockLog)
  89:              MockLog.Log(LogLevel.Information, "MockLog")
  90:              ShowServive()
  91:          End Sub
  92:   
  93:          <Test>
  94:          Public Sub TestCoreControllerWithMockLog()
  95:              AddMockLoggerSimple()
  96:              CreateMiddlwareInstance()
  97:              Dim Controller1 As New CoreLinux.TestController(AuWcf1, MockLog)
  98:              Dim Response As IActionResult = Controller1.Index()
  99:              Dim Content As ContentResult = Response
 100:              TestContext.WriteLine(Content.Content)
 101:              Assert.AreEqual(Content.ContentType, "text/html")
 102:          End Sub
 103:   
 104:          <Test>
 105:          Public Sub AddRealLogger()
 106:              CreateMiddlwareInstance()
 107:              Dim _LoggerFactory = LoggerFactory.Create(Sub(Builder) Builder.AddConsole())
 108:              RealLog = _LoggerFactory.CreateLogger(Of CoreLinux.TestController)
 109:              CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), RealLog)
 110:              RealLog.LogInformation("Test RealLog")
 111:              ShowServive()
 112:          End Sub
 113:   
 114:          <Test>
 115:          Public Sub TestCoreControllerWithRealLog()
 116:              CreateMiddlwareInstance()
 117:              AddRealLogger()
 118:              Dim Controller1 As New CoreLinux.TestController(AuWcf1, RealLog)
 119:              Dim Response As IActionResult = Controller1.Index()
 120:              Dim Content As ContentResult = Response
 121:              TestContext.WriteLine(Content.Content)
 122:              Assert.AreEqual(Content.ContentType, "text/html")
 123:          End Sub
 124:   
 125:      End Class
 126:   
 127:  End Namespace


12. Add memory cache layer (EF db definition).

Than. to improve prformance, I decide create additional layer, a memory cache in Linux machine for data reading from SQL2005. For this perpose, I define a DB:


   1:  Imports Microsoft.EntityFrameworkCore
   2:  Imports System
   3:  Imports System.Collections.Generic
   4:  Imports System.ComponentModel.DataAnnotations
   5:  Imports System.Linq
   6:  Public Class InMemoryDBContext
   7:      Inherits DbContext
   8:   
   9:      Public Sub New(ByVal options As DbContextOptions(Of InMemoryDBContext))
  10:          MyBase.New(options)
  11:      End Sub
  12:   
  13:      Public Property GraphHoperKeys As DbSet(Of RetGraphHoperKey)
  14:      Public Property BotIps As DbSet(Of RetBlockIP)
  15:   
  16:      Public Property LocaRoutesCache As DbSet(Of LocalCache)
  17:   
  18:  End Class
  19:   
  20:  Public Class RetBlockIP
  21:      <Key>
  22:      Public Property I As Long
  23:      Public Property BlockNet As String
  24:  End Class
  25:  Public Class RetGraphHoperKey
  26:      <Key>
  27:      Public Property I As Long
  28:      Public Property MasterKey As String
  29:      Public Property RealKey As String
  30:  End Class
  31:  Public Class LocalCache
  32:      <Key>
  33:      Public Property I As Long
  34:      Public URL As String
  35:      Public Property Route As String
  36:      Public Property AddDate As DateTime
  37:  End Class

Initially I want to define DB directly in type produced by ServiceReference1, but sorry there are no key for EntityFramework. I'm forced to create additional define of RetBlockIP and RetGraphHoperKey instead ServiceReference1.RetBlockIP and ServiceReference1.RetGraphHoperKey.

13. Add memory cache layer (add InMemoryDB service) and new service SQLCache.

Than I was add InMemoryDB.



And I have included db to project:


  27:      Public Sub ConfigureServices(ByVal services As IServiceCollection)
  ...   
  36:          services.
  37:              AddDbContext(Of InMemoryDBContext)(Sub(opts) opts.UseInMemoryDatabase("DataFromSql2005"), ServiceLifetime.Singleton)
  ...   
  40:          'services.Add(New ServiceDescriptor(GetType(IAuWcf), New AuWcf()))
  41:          'or
  42:          services.AddSingleton(GetType(IAuWcf), New AuWcf())
  43:   
  44:          services.AddSingleton(GetType(ISQLCache), New SQLCache())

14. Add memory cache layer.

   1:  Public Interface ISQLCache
   2:   
   3:      ReadOnly Property IsActivated As Boolean
   4:      Function Activate(_InMemoryDatabase As InMemoryDBContext, _AuWcf As IAuWcf) As ISQLCache
   5:      ReadOnly Property IsStaticDataLoaded As Boolean
   6:      Function LoadStaticDataToLocalCache() As (GraphHoperKeyCount As Integer, BotIp As Integer)
   7:      Function AddRouteToLocalCache(I As Long, CacheURL As String, Route As String) As Integer
   8:      Function GetRouteFromLocalCache(CacheURL As String) As String
   9:   
  10:  End Interface

Than I implemented this interface interface:


   1:  Imports Microsoft.AspNetCore.Http
   2:   
   3:  Public Class SQLCache
   4:      Implements ISQLCache
   5:   
   6:      Property InMemoryDatabase As InMemoryDBContext
   7:      Property AuWcf As IAuWcf
   8:   
   9:      Public ReadOnly Property IsActivated As Boolean Implements ISQLCache.IsActivated
  10:          Get
  11:              Return _IsActivated
  12:          End Get
  13:      End Property
  14:      Property _IsActivated As Boolean = False
  15:   
  16:      Public Function Activate(_InMemoryDatabase As InMemoryDBContext, _AuWcf As IAuWcf) As ISQLCache Implements ISQLCache.Activate
  17:          InMemoryDatabase = _InMemoryDatabase
  18:          AuWcf = _AuWcf
  19:          _IsActivated = True
  20:          Return Me
  21:      End Function
  22:      Public ReadOnly Property IsStaticDataLoaded As Boolean Implements ISQLCache.IsStaticDataLoaded
  23:          Get
  24:              Return _IsStaticDataLoaded
  25:          End Get
  26:      End Property
  27:      Property _IsStaticDataLoaded = False
  28:   
  29:      Public Async Function InvokeAsync(ByVal context As HttpContext, ByVal NextDelegate As RequestDelegate, _InMemoryDatabase As InMemoryDBContext, _AuWcf As IAuWcf) As Task
  30:          Await NextDelegate(context)
  31:      End Function
  32:   
  33:      Public Function LoadStaticDataToLocalCache() As (GraphHoperKeyCount As Integer, BotIp As Integer) Implements ISQLCache.LoadStaticDataToLocalCache
  34:          If Not InMemoryDatabase.GraphHoperKeys.Any Then
  35:              Dim Ret1 = AuWcf.AuGetGrapHoperKey()
  36:              Ret1.ToList.ForEach(Sub(One) InMemoryDatabase.GraphHoperKeys.Add(New RetGraphHoperKey With {.I = One.I, .MasterKey = One.MasterKey, .RealKey = One.RealKey}))
  37:          End If
  38:          If Not InMemoryDatabase.BotIps.Any Then
  39:              Dim Ret2 = AuWcf.AuGetBlockIP()
  40:              Ret2.ToList.ForEach(Sub(one) InMemoryDatabase.BotIps.AddRange(New RetBlockIP With {.I = one.I, .BlockNet = one.BlockNet}))
  41:          End If
  42:          InMemoryDatabase.SaveChanges()
  43:          _IsStaticDataLoaded = True
  44:          Return (InMemoryDatabase.GraphHoperKeys.Count, InMemoryDatabase.BotIps.Count)
  45:      End Function
  46:   
  47:      Public Function AddRouteToLocalCache(I As Long, CacheURL As String, Route As String) As Integer Implements ISQLCache.AddRouteToLocalCache
  48:          AddRouteToLocalCache = InMemoryDatabase.LocaRoutesCache.Count
  49:          If AddRouteToLocalCache >= 100 Then
  50:              Dim OldestRow = InMemoryDatabase.LocaRoutesCache.OrderByDescending(Of DateTime)(Function(X) X.AddDate).Take(1)
  51:              InMemoryDatabase.LocaRoutesCache.Remove(OldestRow)
  52:              InMemoryDatabase.SaveChanges()
  53:          End If
  54:          InMemoryDatabase.LocaRoutesCache.Add(New LocalCache With {.I = I, .AddDate = Now, .URL = CacheURL, .Route = Route})
  55:      End Function
  56:   
  57:      Public Function GetRouteFromLocalCache(CacheURL As String) As String Implements ISQLCache.GetRouteFromLocalCache
  58:          Return InMemoryDatabase.LocaRoutesCache.Where(Function(X) X.URL = CacheURL).FirstOrDefault.Route
  59:      End Function
  60:   
  61:  End Class

15. TestController code to call cache layer.

This way allow me to avoid activation middleware by Invoke and simplify my code.


   1:  Imports System
   2:  Imports System.Collections.Generic
   3:  Imports System.Linq
   4:  Imports System.Threading.Tasks
   5:  Imports Microsoft.AspNetCore.Http
   6:  Imports Microsoft.AspNetCore.Mvc
   7:  Imports Microsoft.AspNetCore.Authorization
   8:  Imports Newtonsoft.Json
   9:  Imports Microsoft.Extensions.Logging
  10:  Imports Microsoft.EntityFrameworkCore.InMemory.Storage.Internal
  11:   
  12:  <Route("[controller]")>
  13:  <ApiController>
  14:  <ServiceFilter(GetType(AuditAttribute))>
  15:  Public Class TestController
  16:      Inherits ControllerBase
  17:   
  18:      Property SQL2005 As IAuWcf
  19:      Property Logger As ILogger(Of TestController)
  20:      Property InMemoryDatabase As InMemoryDBContext
  21:      Property SQLCache As ISQLCache
  22:   
  23:      Public Sub New(_SQL2005 As IAuWcf, _Logger As ILogger(Of TestController), _InMemoryDatabase As InMemoryDBContext, _SQLCache As ISQLCache)
  24:          SQL2005 = _SQL2005
  25:          Logger = _Logger
  26:          InMemoryDatabase = _InMemoryDatabase
  27:          If Not _SQLCache.IsActivated Then _SQLCache.Activate(_InMemoryDatabase, _SQL2005)
  28:          If Not _SQLCache.IsStaticDataLoaded Then _SQLCache.LoadStaticDataToLocalCache()
  29:          SQLCache = _SQLCache
  30:      End Sub
  31:   
  32:      Public Function Index() As ActionResult
  33:          '      If Logger IsNot Nothing Then Logger.Log(LogLevel.Information, $"GraphHoperKeyCount={CacheCount.GraphHoperKeyCount}, BotIp={CacheCount.BotIp}")
  34:          Dim D As New ObjectDumper
  35:          Dim Str1 As String = D.Dump(3, Request)
  36:          SQL2005.AuAddTrace(Str1)
  37:          Return Content(String.Format("<html><body><img src='asp_net_core_3_1_vb_GDH_icon.ico'><pre>{0}</pre></body></html>", Str1), "text/html")
  38:      End Function
  39:   
  40:  End Class

16. Test memory cache layer (Nunit).

Than I have created test for my middleware. I made big mistake and spend for this test more times than to code, I was want receive dbContext as result of string 52, and finally I realized my mistake and create context for testing from scratch in line 53.


   1:  Imports NUnit.Framework
   2:  Imports Moq
   3:  Imports Microsoft.AspNetCore.Hosting
   4:  Imports Microsoft.Extensions.DependencyInjection
   5:  Imports Microsoft.Extensions.Hosting
   6:  Imports Microsoft.Extensions.Logging
   7:  Imports Microsoft.Extensions.Logging.Abstractions
   8:  Imports CoreLinux
   9:  Imports Newtonsoft.Json
  10:  Imports Microsoft.AspNetCore.Mvc
  11:  Imports Microsoft.EntityFrameworkCore
  12:   
  13:  Namespace CoreLinuxNUnitTest1
  14:   
  15:      Public Class Tests
  16:          Property CoreDIserviceCollection As IServiceCollection
  17:          Property CoreDIserviceProvider As ServiceProvider
  18:          Property MockLog As ILogger(Of CoreLinux.TestController)
  19:          Property RealLog As ILogger(Of CoreLinux.TestController)
  20:          Property AuWcf1 As AuWcf
  21:          Property InMemoryDBContext1 As InMemoryDBContext
  22:          Property SQLCache1 As ISQLCache
  23:   
  24:          <SetUp>
  25:          Public Sub Setup()
  26:              CoreDIserviceCollection = New ServiceCollection()
  27:              CoreDIserviceProvider = CoreDIserviceCollection.AddLogging.BuildServiceProvider()
  28:          End Sub
  29:   
  30:          <Test>
  31:          Public Sub ShowServive()
  32:              Dim Str1 As New Text.StringBuilder
  33:              CoreDIserviceCollection.ToList.ForEach(Sub(ServiceDescriptor)
  34:                                                         Str1.Append(ServiceDescriptor.Lifetime.ToString & " : ")
  35:                                                         Str1.AppendLine(ServiceDescriptor.ServiceType.FullName)
  36:                                                     End Sub)
  37:              Assert.IsTrue(CoreDIserviceCollection.Count > 0)
  38:              TestContext.WriteLine("CoreDI builded " & CoreDIserviceCollection.Count & " services" & vbCrLf & Str1.ToString)
  39:              TestContext.WriteLine()
  40:          End Sub
  41:   
  42:          <Test>
  43:          Public Sub CreateAuWcfInstance()
  44:              AuWcf1 = New AuWcf()
  45:              Assert.AreEqual(5, AuWcf1.WcfConfig.Count)
  46:              TestContext.WriteLine("WcfConfig" & vbCrLf & JsonConvert.SerializeObject(AuWcf1.WcfConfig, Formatting.Indented))
  47:              TestContext.WriteLine()
  48:          End Sub
  49:   
  50:          <Test>
  51:          Public Sub TestAuWcfGetKeys()
  52:              CreateAuWcfInstance()
  53:              Dim x = AuWcf1.AuGetGrapHoperKey()
  54:              TestContext.WriteLine()
  55:          End Sub
  56:   
  57:          <Test>
  58:          Public Sub CreateInMemoryDbInstance()
  59:              'wrong way
  60:              CoreDIserviceCollection.AddDbContext(Of InMemoryDBContext)(Sub(opts) opts.UseInMemoryDatabase("DataFromSql2005"), ServiceLifetime.Singleton)
  61:              Dim InMemoryDBContextService = CoreDIserviceCollection.Where(Function(y) y.ServiceType.FullName = "CoreLinux.InMemoryDBContext").First
  62:              ShowServive()
  63:              'correct way
  64:              Dim DbOptions = New DbContextOptionsBuilder(Of InMemoryDBContext)().UseInMemoryDatabase(databaseName:="DataFromSql2005").Options
  65:              InMemoryDBContext1 = New InMemoryDBContext(DbOptions)
  66:          End Sub
  67:   
  68:          Public Sub CreateSQLCacheInstance()
  69:              CreateAuWcfInstance()
  70:              CreateInMemoryDbInstance()
  71:              SQLCache1 = New SQLCache()
  72:              If Not SQLCache1.IsActivated Then SQLCache1.Activate(InMemoryDBContext1, AuWcf1)
  73:              Dim CacheCount As ValueTuple(Of Integer, Integer)
  74:              If Not SQLCache1.IsStaticDataLoaded Then
  75:                  CacheCount = SQLCache1.LoadStaticDataToLocalCache()
  76:                  TestContext.WriteLine("WcfConfig" & $"GraphHoperKeyCount={CacheCount.Item1}, BotIp={CacheCount.Item2}")
  77:              End If
  78:              Assert.IsTrue(SQLCache1.IsActivated)
  79:          End Sub
  80:   
  81:          <Test>
  82:          Public Sub TestCoreSingletonServiceFactory()
  83:              ShowServive()
  84:              CreateAuWcfInstance()
  85:              CoreDIserviceCollection.AddSingleton(GetType(IAuWcf), AuWcf1)
  86:              Dim Res As String = AuWcf1.AuTest(10)
  87:              Assert.AreEqual("10", Res)
  88:              ShowServive()
  89:          End Sub
  90:   
  91:          <Test>
  92:          Public Sub AddMockLoggerWithOwnImpl()
  93:              ShowServive()
  94:              Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
  95:              MockLog = _Mock.Object
  96:              Dim MockLogger1 As MockLogger = New MockLogger()
  97:              MockLogger1.LogLevel = LogLevel.Information Or LogLevel.Error Or LogLevel.Warning Or LogLevel.Trace Or LogLevel.Debug Or LogLevel.Trace
  98:              CoreDIserviceCollection.AddSingleton(Of ILoggerFactory)(Function(s)
  99:                                                                          Dim loggerFactoryMock = New Mock(Of ILoggerFactory)()
 100:                                                                          loggerFactoryMock.Setup(Function(m) m.CreateLogger(It.IsAny(Of String)())).Returns(MockLogger1)
 101:                                                                          Return loggerFactoryMock.Object
 102:                                                                      End Function)
 103:   
 104:              MockLog.Log(LogLevel.Information, "MockLog")
 105:              ShowServive()
 106:          End Sub
 107:   
 108:          <Test>
 109:          Public Sub AddMockLoggerSimple()
 110:              Dim _Mock = New Mock(Of ILogger(Of CoreLinux.TestController))
 111:              MockLog = _Mock.Object
 112:              CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), MockLog)
 113:              MockLog.Log(LogLevel.Information, "MockLog")
 114:              ShowServive()
 115:          End Sub
 116:   
 117:          <Test>
 118:          Public Sub TestCoreControllerWithMockLog()
 119:              AddMockLoggerSimple()
 120:              CreateSQLCacheInstance()
 121:              Dim Controller1 As New CoreLinux.TestController(AuWcf1, MockLog, InMemoryDBContext1, SQLCache1)
 122:              Dim Response As IActionResult = Controller1.Index()
 123:              Dim Content As ContentResult = Response
 124:              TestContext.WriteLine(Content.Content)
 125:              Assert.AreEqual(Content.ContentType, "text/html")
 126:          End Sub
 127:   
 128:          <Test>
 129:          Public Sub AddRealLogger()
 130:              CreateAuWcfInstance()
 131:              Dim _LoggerFactory = LoggerFactory.Create(Sub(Builder) Builder.AddConsole())
 132:              RealLog = _LoggerFactory.CreateLogger(Of CoreLinux.TestController)
 133:              CoreDIserviceCollection.AddSingleton(GetType(ILogger(Of TestController)), RealLog)
 134:              RealLog.LogInformation("Test RealLog")
 135:              ShowServive()
 136:          End Sub
 137:   
 138:          <Test>
 139:          Public Sub TestCoreControllerWithRealLog()
 140:              AddRealLogger()
 141:              CreateInMemoryDbInstance()
 142:              CreateSQLCacheInstance()
 143:              Dim Controller1 As New CoreLinux.TestController(AuWcf1, RealLog, InMemoryDBContext1, SQLCache1)
 144:              Dim Response As IActionResult = Controller1.Index()
 145:              Dim Content As ContentResult = Response
 146:              TestContext.WriteLine(Content.Content)
 147:              Assert.AreEqual(Content.ContentType, "text/html")
 148:          End Sub
 149:   
 150:      End Class
 151:   
 152:  End Namespace

As you can see, memory cache in Linux machine with data from SQL2005 working perfectly:



17. Integration test to write data to remote SQL2005.

And finally I want to return to my first screen on top of this post - this is my integration test to write data from Core Linux daemon to remote SQL2005.



Its a really fantastic - Linux daemon has permanent connection to MS SQL2005 and read (with cache) and write data to MS SQL2005. Also this project compose many different layer and each layer need to be testing separately, therefore I have decided write down particular post about TDD (test driven development) on the example of this project TDD in Core Linux (Middleware, IdentityServer, SignalR, Quartz, RabbitMQ, Redis and so on).

18. Remote debugging and monitoring




Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20
Link to this page: http://www.vb-net.com/NetCoreDaemonExecAncientMsSQLProcedure/Index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <MAIL ME>  <ABOUT ME>  < THANKS ME>