I have tested C# compilation under VS Online.
This kind of paid products is not for me. As a developer, I build on a local machine and I want to be offline and not always connected. More, I don’t want to pay for and IDE and a free compiler.
Visual C++ and Native Development (C++ Renaissance) and .NET Technologies and life's stuff on computers
You have an IT solution with 4.000.000 lines of code. You want an audit ? What need to be rewritten, cut, reorganized. Want some ideas ? I can give you ideas with one hour !
You want to migrate your legacy apps into a modern Microsoft solution ?
You want to put some deprecated stuff on Docker, reorganize some others stuff ?
You need to look at a large amount of various source code ? You are lost with your source code, I can help !
You have old Microsoft technologies, ASP.NET Forms, various ASP.NEt MVC appz, WinForms or WPF APps, C++ Win32 or MFC Appz and you want to stay on the edge ? Call me !
For a NET Core 3 Folder, I have written two articles:
LMDBNet is aviailable : https://www.nuget.org/packages/LMDBNet/1.1.0
The package contains the relase and debug version of LMDBNet.dll NET bindings with LMDBWindowsDll64.dll and LMDBWindowsDllD64.dll, the migrated Linux lib ported on Windows as a standard DLL.
VCREDIST is not inside the package.
I am proud to lead the community of NET Azure Rangers. This month, in french magazine Programmez for April 2019 issue, we have written 3 artciles.
My article is available in kiosk this month.
On Monday 3, I will make a demo in my company about Docker/Azure and I have decided to make a demo about C# .NET stuff because few people are interested in C++… So I have rewritten my service in C#. It was not very difficult:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using LMDBNet; using Newtonsoft.Json; namespace LMDBServiceNet { class WebServer { HttpListener _listener; LMDBWrapper _wrapper; public WebServer(string uriPrefix) { _listener = new HttpListener(); _listener.Prefixes.Add(uriPrefix); _wrapper = new LMDBWrapper(); _wrapper.Init("cache_db"); } public async void Start() { _listener.Start(); while (true) try { var context = await _listener.GetContextAsync(); Task.Run(() => ProcessRequestAsync(context)); } catch (HttpListenerException) { break; } // Listener stopped. catch (InvalidOperationException) { break; } // Listener stopped. } public void Stop() { _listener.Stop(); } async void ProcessRequestAsync(HttpListenerContext context) { try { string request = Path.GetFileName(context.Request.RawUrl); string str = String.Format("you asked for: {0}", request); //Console.WriteLine(str); Dictionary<string, string> parameters = ExtractParameters(context); if (parameters.Count == 0) { await WriteResponse(context, String.Empty, HttpStatusCode.OK); return; } string verb; if ( parameters.TryGetValue("request", out verb) == false ) { await WriteResponse(context, String.Empty, HttpStatusCode.OK); return; } if (context.Request.HttpMethod == "GET") { if (verb == Constants.VerbPing) { await RequestVerbPing(context); return; } else if (verb == Constants.VerbUsage) { await RequestUsage(context); return; } else if (verb == Constants.VerbGetData) { await RequestVerbGetData(context, parameters); return; } else if (verb == Constants.VerbSetData) { await RequestVerbSetData(context, parameters); return; } } await WriteResponse(context, String.Empty, HttpStatusCode.OK); } catch (Exception ex) { Console.WriteLine("Request error: " + ex); } } private Dictionary<string, string> ExtractParameters(HttpListenerContext context) { string request = Path.GetFileName(context.Request.RawUrl); string str = String.Format("Request: {0}", request); //Console.WriteLine(str); //http://192.168.175.241:7001/MyServer/LMDB/?request=set-data&key=toto0&value=toto1&name=cache2 Dictionary<string, string> parameters = new Dictionary<string, string>(); if (String.IsNullOrEmpty(request)) return parameters; var strings = request.Split('&'); if (strings == null) return parameters; if (strings.Length >= 1) { strings[0] = strings[0].Remove(0, 1); } else { return parameters; } foreach (string s in strings) { //Console.WriteLine(s); var data = s.Split('='); if( data.Length == 2) { string values = String.Format("{0}:{1}", data[0], data[1]); //Console.WriteLine(values); parameters.Add(data[0], data[1]); } } return parameters; } private async Task WriteResponse(HttpListenerContext context, string message, HttpStatusCode code) { Logger.LogInfo(message); var enc = Encoding.UTF8; byte[] msg = enc.GetBytes(message); context.Response.StatusCode = (int)code; context.Response.ContentLength64 = msg.Length; using (Stream s = context.Response.OutputStream) await s.WriteAsync(msg, 0, msg.Length); } private async Task RequestUsage(HttpListenerContext context) { DataUsage usage = new DataUsage(); usage.company = "NEOS-SDI"; usage.developer = "Christophe Pichaud"; usage.version = "August 2008 BETA 0.3 .NET C#"; string str = JsonConvert.SerializeObject(usage); await WriteResponse(context, str, HttpStatusCode.OK); } private async Task RequestVerbPing(HttpListenerContext context) { DataPing ping = new DataPing(); ping.ip = "localhost"; ping.port = Constants.MasterNodePort; ping.server = Environment.MachineName; string str = JsonConvert.SerializeObject(ping); await WriteResponse(context, str, HttpStatusCode.OK); } private async Task RequestVerbSetData(HttpListenerContext context, Dictionary<string, string> parameters) { string key; string value; if (parameters.TryGetValue("key", out key) == false || parameters.TryGetValue("value", out value) == false) { await WriteResponse(context, String.Empty, HttpStatusCode.OK); return; } _wrapper.SetData(key, value); Data data = new Data(); data.Key = key; data.Value = value; string str = JsonConvert.SerializeObject(data); await WriteResponse(context, str, HttpStatusCode.OK); } private async Task RequestVerbGetData(HttpListenerContext context, Dictionary<string, string> parameters) { string key; string value; if (parameters.TryGetValue("key", out key) == false) { await WriteResponse(context, String.Empty, HttpStatusCode.OK); return; } _wrapper.GetData(key, out value); Data data = new Data(); data.Key = key; data.Value = value; string str = JsonConvert.SerializeObject(data); await WriteResponse(context, str, HttpStatusCode.OK); } } }
Since few months, I work on LMDB for Azure stuff. First, I have:
Now, I have setup the Azure Web App Svc for hosting a simple file uploader where files will be stored in LMDB NoSQL database. The way of using it is so simple :
private static void StoreFile(string path) { string key = path; string value = String.Empty; byte[] buffer = File.ReadAllBytes(path); LMDBEnvironment _env; string dir = "c:\\temp\\cache_net10B"; _env = new LMDBEnvironment(dir); _env.MaxDatabases = 2; _env.MapSize = 10485760 * 100; _env.Open(); DateTime dtStart = DateTime.Now; var tx = _env.BeginTransaction(); var db = tx.OpenDatabase("DB", new DatabaseConfiguration { Flags = DatabaseOpenFlags.Create }); var enc = System.Text.Encoding.UTF8; tx.Put(db, enc.GetBytes(key), buffer); tx.Commit(); db.Dispose(); DateTime dtStop = DateTime.Now; TimeSpan ts = dtStop - dtStart; string str = String.Format("Time elapsed for set:{0} ms", ts.TotalMilliseconds); Logger.LogInfo(str); _env.Dispose(); }
If you want to test LMDB in your environement, download that stuff:
Download the LMDB Windows DLL and console_app.Exe
Download the LMDB Windows DLL, the .NET WRapper DLL and console_app.Exe
Here is a little sample of code I have written to simulate a cache, wich write the data every second on disk in the background in a dedicted thread.
Using this class Engine, you can write data to the internal dictionary and keep it safe because the database is written to disk… I do not have handled the reload of the data in the ctor… Here the client program who write any number of values you want:
If I run the console application using different values, here is the result:
D:\Dev\MyCache\ConsoleApp1\bin\Debug>ConsoleApp1.exe 10
Count: 10
Time elapsed set: 0 ms
Time elapsed get: 0 ms
Writing DB…
Writing DB OK
D:\Dev\MyCache\ConsoleApp1\bin\Debug>ConsoleApp1.exe 100
Count: 100
Time elapsed set: 0 ms
Time elapsed get: 0 ms
Writing DB…
Writing DB OK
D:\Dev\MyCache\ConsoleApp1\bin\Debug>ConsoleApp1.exe 1000
Count: 1000
Time elapsed set: 1 ms
Time elapsed get: 1 ms
Writing DB…
Writing DB OK
D:\Dev\MyCache\ConsoleApp1\bin\Debug>ConsoleApp1.exe 10000
Count: 10000
Time elapsed set: 7 ms
Time elapsed get: 13 ms
Writing DB…
Writing DB OK
D:\Dev\MyCache\ConsoleApp1\bin\Debug>ConsoleApp1.exe 100000
Count: 100000
Time elapsed set: 98 ms
Time elapsed get: 140 ms
Writing DB…
Writing DB OK
D:\Dev\MyCache\ConsoleApp1\bin\Debug>ConsoleApp1.exe 1000000
Count: 1000000
Writing DB…
Writing DB OK
Time elapsed set: 3656 ms
Time elapsed get: 4023 ms
Writing DB…
Writing DB OK
Source code here: MyCache.zip