diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/Column.cs b/WelsonJS.Toolkit/WelsonJS.Esent/Column.cs index a5274ba..b23dc67 100644 --- a/WelsonJS.Toolkit/WelsonJS.Esent/Column.cs +++ b/WelsonJS.Toolkit/WelsonJS.Esent/Column.cs @@ -1,6 +1,6 @@ // Column.cs (WelsonJS.Esent) // SPDX-License-Identifier: MIT -// SPDX-FileCopyrightText: 2025 Namhyeon Go, Catswords OSS and WelsonJS Contributors +// SPDX-FileCopyrightText: 2025 Namhyeon Go , Catswords OSS and WelsonJS Contributors // https://github.com/gnh1201/welsonjs // using System; diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/DataStore.cs b/WelsonJS.Toolkit/WelsonJS.Esent/EsentDatabase.cs similarity index 92% rename from WelsonJS.Toolkit/WelsonJS.Esent/DataStore.cs rename to WelsonJS.Toolkit/WelsonJS.Esent/EsentDatabase.cs index 0842913..ef0a71e 100644 --- a/WelsonJS.Toolkit/WelsonJS.Esent/DataStore.cs +++ b/WelsonJS.Toolkit/WelsonJS.Esent/EsentDatabase.cs @@ -1,6 +1,6 @@ // DataStore.cs (WelsonJS.Esent) // SPDX-License-Identifier: MIT -// SPDX-FileCopyrightText: 2025 Namhyeon Go, Catswords OSS and WelsonJS Contributors +// SPDX-FileCopyrightText: 2025 Namhyeon Go , Catswords OSS and WelsonJS Contributors // https://github.com/gnh1201/welsonjs // using System; @@ -13,11 +13,13 @@ using Microsoft.Isam.Esent.Interop; namespace WelsonJS.Esent { - public class DataStore : IDisposable + public class EsentDatabase : IDisposable { private const string _primaryKeyindexName = "primary"; private const string _indexNamePrefix = "idx_"; + private const string _databaseName = "metadata.edb"; + private readonly ICompatibleLogger _logger; private static readonly object _lock = new object(); private static bool _initialized = false; private static Instance _instance; @@ -30,8 +32,10 @@ namespace WelsonJS.Esent private readonly Column _primaryKey; private readonly Dictionary _columnIds; - public DataStore(Schema schema, string workingDirectory) + public EsentDatabase(Schema schema, string workingDirectory, ICompatibleLogger logger = null) { + _logger = logger ?? new TraceLogger(); + _primaryKey = schema.PrimaryKey; if (schema == null) @@ -74,10 +78,10 @@ namespace WelsonJS.Esent if (_initialized) return; // set the file path - _filePath = Path.Combine(_workingDirectory, "metadata.edb"); + _filePath = Path.Combine(_workingDirectory, _databaseName); // config the instance - _instance = new Instance("WelsonJS.Launcher.MetadataStore"); + _instance = new Instance(typeof(EsentDatabase).Namespace); _instance.Parameters.SystemDirectory = _workingDirectory; _instance.Parameters.LogFileDirectory = _workingDirectory; _instance.Parameters.TempDirectory = _workingDirectory; @@ -160,7 +164,7 @@ namespace WelsonJS.Esent } catch (EsentColumnNotFoundException) { - Trace.TraceWarning($"Column '{col.Name}' not found."); + _logger.Warn($"Column '{col.Name}' not found."); } } } @@ -201,7 +205,7 @@ namespace WelsonJS.Esent if (expectSeek != found) { - Trace.TraceWarning($"[ESENT] Operation skipped. Seek result = {found}, expected = {expectSeek}"); + _logger.Warn($"[ESENT] Operation skipped. Seek result = {found}, expected = {expectSeek}"); Api.JetRollback(_session, RollbackTransactionGrbit.None); return false; } @@ -312,7 +316,7 @@ namespace WelsonJS.Esent case JET_coltyp.LongBinary: return Api.RetrieveColumn(session, table, columnId); default: - Trace.TraceWarning($"[ESENT] Unsupported RetrieveColumn type: {type}"); + _logger.Warn($"[ESENT] Unsupported RetrieveColumn type: {type}"); return null; } } @@ -323,13 +327,13 @@ namespace WelsonJS.Esent if (!values.TryGetValue(_primaryKey.Name, out keyValue)) { - Trace.TraceWarning($"[ESENT] Missing primary key '{_primaryKey.Name}'."); + _logger.Warn($"[ESENT] Missing primary key '{_primaryKey.Name}'."); return false; } if (keyValue == null) { - Trace.TraceWarning("[ESENT] Primary key value cannot be null."); + _logger.Warn("[ESENT] Primary key value cannot be null."); return false; } @@ -351,7 +355,7 @@ namespace WelsonJS.Esent { if (!_columnIds.TryGetValue(kv.Key, out var colid)) { - Trace.TraceWarning($"[ESENT] Column '{kv.Key}' not found in cache."); + _logger.Warn($"[ESENT] Column '{kv.Key}' not found in cache."); continue; } @@ -384,7 +388,7 @@ namespace WelsonJS.Esent Api.SetColumn(session, table, columnId, (byte[])value); break; default: - Trace.TraceWarning($"[ESENT] Unsupported SetColumn type: {type}"); + _logger.Warn($"[ESENT] Unsupported SetColumn type: {type}"); break; } } @@ -410,7 +414,7 @@ namespace WelsonJS.Esent Api.MakeKey(session, table, (byte[])value, MakeKeyGrbit.NewKey); break; default: - Trace.TraceWarning($"[ESENT] Unsupported MakeKey type: {type}"); + _logger.Warn($"[ESENT] Unsupported MakeKey type: {type}"); break; } } diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/ICompatibleLogger.cs b/WelsonJS.Toolkit/WelsonJS.Esent/ICompatibleLogger.cs new file mode 100644 index 0000000..2af7225 --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Esent/ICompatibleLogger.cs @@ -0,0 +1,17 @@ +// ICompatibleLogger.cs (WelsonJS.Esent) +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2025 Namhyeon Go , Catswords OSS and WelsonJS Contributors +// https://github.com/gnh1201/welsonjs +// +// We use the ICompatibleLogger interface to maintain a BCL-first style. +// This allows for later replacement with logging libraries such as ILogger or Log4Net. +// +namespace WelsonJS.Esent +{ + public interface ICompatibleLogger + { + void Info(string message); + void Warn(string message); + void Error(string message); + } +} diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/README.md b/WelsonJS.Toolkit/WelsonJS.Esent/README.md new file mode 100644 index 0000000..38d3a7d --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Esent/README.md @@ -0,0 +1,58 @@ +# WelsonJS.Esent + +WelsonJS.Esent is a library that enables the use of the [ESENT](https://learn.microsoft.com/en-us/windows/win32/extensible-storage-engine/extensible-storage-engine) database (also known as the Extensible Storage Engine or JET Blue). + +Although it was developed to support the WelsonJS framework, it can be used in any .NET-based project. + +For more details, refer to the [WelsonJS Documentation](https://catswords-oss.rdbl.io/5719744820/5330609327). + +## Example code + +```csharp +using WelsonJS.Esent; + +// connect the database to manage an instances +Schema schema = new Schema("Instances", new List +{ + new Column("InstanceId", typeof(string), 255), + new Column("FirstDeployTime", typeof(DateTime), 1) +}); +schema.SetPrimaryKey("InstanceId"); +_db = new EsentDatabase(schema, Path.GetTempPath()); + +// Insert row +try +{ + _db.Insert(new Dictionary + { + ["InstanceId"] = instanceId, + ["FirstDeployTime"] = now + }, out _); +} +catch (Exception ex) +{ + // Handle exception +} + +// find all +var instances = _db.FindAll(); +foreach (var instance in instances) +{ + try + { + string instanceId = instance["InstanceId"].ToString(); + string firstDeployTime = instance.ContainsKey("FirstDeployTime") + ? ((DateTime)instance["FirstDeployTime"]).ToString(_dateTimeFormat) + : "Unknown"; + + Console.WriteLine($"{firstDeployTime}, {instanceId}"); + } + catch (Exception ex) + { + // Handle exception + } +} + +``` + +Source code available: https://github.com/gnh1201/welsonjs diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/Schema.cs b/WelsonJS.Toolkit/WelsonJS.Esent/Schema.cs index 66b3ea1..1bfaa27 100644 --- a/WelsonJS.Toolkit/WelsonJS.Esent/Schema.cs +++ b/WelsonJS.Toolkit/WelsonJS.Esent/Schema.cs @@ -1,6 +1,6 @@ // Schema.cs (WelsonJS.Esent) // SPDX-License-Identifier: MIT -// SPDX-FileCopyrightText: 2025 Namhyeon Go, Catswords OSS and WelsonJS Contributors +// SPDX-FileCopyrightText: 2025 Namhyeon Go , Catswords OSS and WelsonJS Contributors // https://github.com/gnh1201/welsonjs // using System; diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/TraceLogger.cs b/WelsonJS.Toolkit/WelsonJS.Esent/TraceLogger.cs new file mode 100644 index 0000000..ad6a282 --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Esent/TraceLogger.cs @@ -0,0 +1,19 @@ +// TraceLogger.cs (WelsonJS.Esent) +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2025 Namhyeon Go , Catswords OSS and WelsonJS Contributors +// https://github.com/gnh1201/welsonjs +// +// We use the ICompatibleLogger interface to maintain a BCL-first style. +// This allows for later replacement with logging libraries such as ILogger or Log4Net. +// +using System.Diagnostics; + +namespace WelsonJS.Esent +{ + public class TraceLogger : ICompatibleLogger + { + public void Info(string message) => Trace.TraceInformation(message); + public void Warn(string message) => Trace.TraceWarning(message); + public void Error(string message) => Trace.TraceError(message); + } +} diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/WelsonJS - Backup.Esent.csproj b/WelsonJS.Toolkit/WelsonJS.Esent/WelsonJS - Backup.Esent.csproj new file mode 100644 index 0000000..e8ee38a --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Esent/WelsonJS - Backup.Esent.csproj @@ -0,0 +1,39 @@ + + + + netstandard2.0 + AnyCPU;x86 + WelsonJS.Esent + https://github.com/gnh1201/welsonjs + https://github.com/gnh1201/welsonjs + git + nosql,esent,database + 0.2.7.55 + 0.2.7.55 + MIT + 2025 Namhyeon Go, Catswords OSS and WelsonJS Contributors + Enable ESENT database engine + True + Namhyeon Go,Catswords OSS + + + + + + + + + + + True + \ + Never + + + True + \ + Never + + + + diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/WelsonJS.Esent.csproj b/WelsonJS.Toolkit/WelsonJS.Esent/WelsonJS.Esent.csproj index 480cb78..5e1649e 100644 --- a/WelsonJS.Toolkit/WelsonJS.Esent/WelsonJS.Esent.csproj +++ b/WelsonJS.Toolkit/WelsonJS.Esent/WelsonJS.Esent.csproj @@ -4,10 +4,40 @@ netstandard2.0 AnyCPU;x86 WelsonJS.Esent + https://github.com/gnh1201/welsonjs + https://github.com/gnh1201/welsonjs + git + nosql,esent,database + 0.2.7.55 + 0.2.7.55 + MIT + 2025 Namhyeon Go, Catswords OSS and WelsonJS Contributors + Enable ESENT database engine + True + Namhyeon Go,Catswords OSS + + + + + True + \ + Never + + + True + \ + Never + + + \ + True + + + diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/assets/docs/README.md b/WelsonJS.Toolkit/WelsonJS.Esent/assets/docs/README.md new file mode 100644 index 0000000..38d3a7d --- /dev/null +++ b/WelsonJS.Toolkit/WelsonJS.Esent/assets/docs/README.md @@ -0,0 +1,58 @@ +# WelsonJS.Esent + +WelsonJS.Esent is a library that enables the use of the [ESENT](https://learn.microsoft.com/en-us/windows/win32/extensible-storage-engine/extensible-storage-engine) database (also known as the Extensible Storage Engine or JET Blue). + +Although it was developed to support the WelsonJS framework, it can be used in any .NET-based project. + +For more details, refer to the [WelsonJS Documentation](https://catswords-oss.rdbl.io/5719744820/5330609327). + +## Example code + +```csharp +using WelsonJS.Esent; + +// connect the database to manage an instances +Schema schema = new Schema("Instances", new List +{ + new Column("InstanceId", typeof(string), 255), + new Column("FirstDeployTime", typeof(DateTime), 1) +}); +schema.SetPrimaryKey("InstanceId"); +_db = new EsentDatabase(schema, Path.GetTempPath()); + +// Insert row +try +{ + _db.Insert(new Dictionary + { + ["InstanceId"] = instanceId, + ["FirstDeployTime"] = now + }, out _); +} +catch (Exception ex) +{ + // Handle exception +} + +// find all +var instances = _db.FindAll(); +foreach (var instance in instances) +{ + try + { + string instanceId = instance["InstanceId"].ToString(); + string firstDeployTime = instance.ContainsKey("FirstDeployTime") + ? ((DateTime)instance["FirstDeployTime"]).ToString(_dateTimeFormat) + : "Unknown"; + + Console.WriteLine($"{firstDeployTime}, {instanceId}"); + } + catch (Exception ex) + { + // Handle exception + } +} + +``` + +Source code available: https://github.com/gnh1201/welsonjs diff --git a/WelsonJS.Toolkit/WelsonJS.Esent/assets/img/logo.png b/WelsonJS.Toolkit/WelsonJS.Esent/assets/img/logo.png new file mode 100644 index 0000000..4790015 Binary files /dev/null and b/WelsonJS.Toolkit/WelsonJS.Esent/assets/img/logo.png differ diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs index 46cfbf4..addd665 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs @@ -15,7 +15,7 @@ { if (disposing && (components != null)) { - _dataStore?.Dispose(); // dispose the database session + _db?.Dispose(); // dispose the database session components.Dispose(); } base.Dispose(disposing); diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs index 5b9c07d..28f2137 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs @@ -18,7 +18,7 @@ namespace WelsonJS.Launcher private string _entryFileName; private string _scriptName; private readonly string _dateTimeFormat; - private readonly DataStore _dataStore; + private readonly EsentDatabase _db; public InstancesForm() { @@ -37,12 +37,12 @@ namespace WelsonJS.Launcher new Column("FirstDeployTime", typeof(DateTime), 1) }); schema.SetPrimaryKey("InstanceId"); - _dataStore = new DataStore(schema, Program.GetAppDataPath()); + _db = new EsentDatabase(schema, Program.GetAppDataPath()); } - public DataStore GetDataStore() + public EsentDatabase GetDatabaseInstance() { - return _dataStore; + return _db; } private void InstancesForm_Load(object sender, EventArgs e) @@ -53,7 +53,7 @@ namespace WelsonJS.Launcher private void LoadInstances() { - var instances = _dataStore.FindAll(); + var instances = _db.FindAll(); foreach (var instance in instances) { try @@ -135,7 +135,7 @@ namespace WelsonJS.Launcher try { Directory.Delete(workingDirectory, true); - _dataStore.DeleteById(instanceId); + _db.DeleteById(instanceId); } catch (Exception ex) { diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs index 6fb6aa7..162d26d 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs @@ -169,7 +169,7 @@ namespace WelsonJS.Launcher InstancesForm instancesForm = new InstancesForm(); try { - instancesForm.GetDataStore().Insert(new Dictionary + instancesForm.GetDatabaseInstance().Insert(new Dictionary { ["InstanceId"] = instanceId, ["FirstDeployTime"] = now