From 4faa34b07fd8de0c76889f92231285a9e920f672 Mon Sep 17 00:00:00 2001 From: Luca Fabbri Date: Sun, 2 Nov 2025 15:58:15 +0100 Subject: [PATCH 1/4] feat: adds support for DataAnnotations attributes ([Key] and [NotMapped]) as aliases for [BsonId] and [BsonIgnore] (for .NET 8+) --- ...ertionIgnoreExpressionPropertyBenchmark.cs | 91 +++- LiteDB.Benchmarks/Models/FileMetaBase.cs | 1 + .../Models/FileMetaBaseComponentModel.cs | 37 ++ .../FileMetaWithExclusionComponentModel.cs | 27 ++ .../Models/Generators/FileMetaGenerator.cs | 6 +- .../FileMetaGeneratorComponentModel.cs | 55 +++ LiteDB.Tests/Mapper/CustomMapping_Tests.cs | 198 ++++++--- LiteDB.sln | 412 ++++++++++-------- .../Mapper/BsonMapper.GetEntityMapper.cs | 49 ++- README.md | 105 ++--- 10 files changed, 669 insertions(+), 312 deletions(-) create mode 100644 LiteDB.Benchmarks/Models/FileMetaBaseComponentModel.cs create mode 100644 LiteDB.Benchmarks/Models/FileMetaWithExclusionComponentModel.cs create mode 100644 LiteDB.Benchmarks/Models/Generators/FileMetaGeneratorComponentModel.cs diff --git a/LiteDB.Benchmarks/Benchmarks/Insertion/InsertionIgnoreExpressionPropertyBenchmark.cs b/LiteDB.Benchmarks/Benchmarks/Insertion/InsertionIgnoreExpressionPropertyBenchmark.cs index 468e5ac05..057de0b6d 100644 --- a/LiteDB.Benchmarks/Benchmarks/Insertion/InsertionIgnoreExpressionPropertyBenchmark.cs +++ b/LiteDB.Benchmarks/Benchmarks/Insertion/InsertionIgnoreExpressionPropertyBenchmark.cs @@ -93,5 +93,94 @@ public void GlobalCleanup() File.Delete(DatabasePath); } - } + } + + + [BenchmarkCategory(Constants.Categories.INSERTION)] + public class InsertionIgnoreExpressionPropertyComponentModelBenchmark : BenchmarkBase + { + private List _baseData; + private List _baseDataWithBsonIgnore; + + private ILiteCollection _fileMetaCollection; + private ILiteCollection _fileMetaExclusionCollection; + + [GlobalSetup(Target = nameof(Insertion))] + public void GlobalBsonIgnoreSetup() + { + File.Delete(DatabasePath); + + DatabaseInstance = new LiteDatabase(ConnectionString()); + _fileMetaCollection = DatabaseInstance.GetCollection(); + _fileMetaCollection.EnsureIndex(fileMeta => fileMeta.ShouldBeShown); + + _baseData = FileMetaGeneratorComponentModel.GenerateList(DatasetSize); // executed once per each N value + } + + [GlobalSetup(Target = nameof(InsertionWithBsonIgnore))] + public void GlobalIgnorePropertySetup() + { + File.Delete(DatabasePath); + + DatabaseInstance = new LiteDatabase(ConnectionString()); + _fileMetaExclusionCollection = DatabaseInstance.GetCollection(); + _fileMetaExclusionCollection.EnsureIndex(fileMeta => fileMeta.ShouldBeShown); + + _baseDataWithBsonIgnore = FileMetaGeneratorComponentModel.GenerateList(DatasetSize); // executed once per each N value + } + + [Benchmark(Baseline = true)] + public int Insertion() + { + var count = _fileMetaCollection.Insert(_baseData); + DatabaseInstance.Checkpoint(); + return count; + } + + [Benchmark] + public int InsertionWithBsonIgnore() + { + var count = _fileMetaExclusionCollection.Insert(_baseDataWithBsonIgnore); + DatabaseInstance.Checkpoint(); + return count; + } + + [IterationCleanup] + public void IterationCleanup() + { + var indexesCollection = DatabaseInstance.GetCollection("$indexes"); + var droppedCollectionIndexes = indexesCollection.Query().Where(x => x["name"] != "_id").ToDocuments().ToList(); + + var collectionNames = DatabaseInstance.GetCollectionNames(); + foreach (var name in collectionNames) + { + DatabaseInstance.DropCollection(name); + } + + foreach (var indexInfo in droppedCollectionIndexes) + { + DatabaseInstance.GetCollection(indexInfo["collection"]) + .EnsureIndex(indexInfo["name"], BsonExpression.Create(indexInfo["expression"]), indexInfo["unique"]); + } + + DatabaseInstance.Checkpoint(); + DatabaseInstance.Rebuild(); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + _baseData?.Clear(); + _baseData = null; + + _baseDataWithBsonIgnore?.Clear(); + _baseDataWithBsonIgnore = null; + + DatabaseInstance?.Checkpoint(); + DatabaseInstance?.Dispose(); + DatabaseInstance = null; + + File.Delete(DatabasePath); + } + } } \ No newline at end of file diff --git a/LiteDB.Benchmarks/Models/FileMetaBase.cs b/LiteDB.Benchmarks/Models/FileMetaBase.cs index 15b7f63aa..23bb94741 100644 --- a/LiteDB.Benchmarks/Models/FileMetaBase.cs +++ b/LiteDB.Benchmarks/Models/FileMetaBase.cs @@ -2,6 +2,7 @@ namespace LiteDB.Benchmarks.Models { + public class FileMetaBase { [BsonIgnore] diff --git a/LiteDB.Benchmarks/Models/FileMetaBaseComponentModel.cs b/LiteDB.Benchmarks/Models/FileMetaBaseComponentModel.cs new file mode 100644 index 000000000..29bddb434 --- /dev/null +++ b/LiteDB.Benchmarks/Models/FileMetaBaseComponentModel.cs @@ -0,0 +1,37 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace LiteDB.Benchmarks.Models +{ + public class FileMetaBaseComponentModel + { + [NotMapped] + public const string BsonIdPropertyKey = "_id"; + + [Key] + public virtual string Id => $"{FileId}_{Version}"; + + public Guid FileId { get; set; } + + public string ParentId { get; set; } + + public string Title { get; set; } + + public string MimeType { get; set; } + + public int Version { get; set; } + + public DateTimeOffset? ValidFrom { get; set; } + + public DateTimeOffset? ValidTo { get; set; } + + public bool IsFavorite { get; set; } + + public bool ShouldBeShown { get; set; } + + public float[] Vectors { get; set; } + + public virtual bool IsValid => ValidFrom == null || ValidFrom <= DateTimeOffset.UtcNow && ValidTo == null || ValidTo > DateTimeOffset.UtcNow; + } +} \ No newline at end of file diff --git a/LiteDB.Benchmarks/Models/FileMetaWithExclusionComponentModel.cs b/LiteDB.Benchmarks/Models/FileMetaWithExclusionComponentModel.cs new file mode 100644 index 000000000..38310639f --- /dev/null +++ b/LiteDB.Benchmarks/Models/FileMetaWithExclusionComponentModel.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace LiteDB.Benchmarks.Models +{ + public class FileMetaWithExclusionComponentModel : FileMetaBaseComponentModel + { + public FileMetaWithExclusionComponentModel() + { + } + + public FileMetaWithExclusionComponentModel(FileMetaBaseComponentModel fileMetaBase) + { + FileId = fileMetaBase.FileId; + ParentId = fileMetaBase.ParentId; + Title = fileMetaBase.Title; + MimeType = fileMetaBase.MimeType; + Version = fileMetaBase.Version; + ValidFrom = fileMetaBase.ValidFrom; + ValidTo = fileMetaBase.ValidTo; + IsFavorite = fileMetaBase.IsFavorite; + ShouldBeShown = fileMetaBase.ShouldBeShown; + } + + [NotMapped] + public override bool IsValid => base.IsValid; + } +} \ No newline at end of file diff --git a/LiteDB.Benchmarks/Models/Generators/FileMetaGenerator.cs b/LiteDB.Benchmarks/Models/Generators/FileMetaGenerator.cs index 903597882..280b356d6 100644 --- a/LiteDB.Benchmarks/Models/Generators/FileMetaGenerator.cs +++ b/LiteDB.Benchmarks/Models/Generators/FileMetaGenerator.cs @@ -10,8 +10,8 @@ namespace LiteDB.Benchmarks.Models.Generators private static T Generate() { - var docGuid = Guid.NewGuid(); - + var docGuid = Guid.NewGuid(); + var generatedFileMeta = new T { FileId = docGuid, @@ -20,7 +20,7 @@ private static T Generate() MimeType = "application/pdf", IsFavorite = _random.Next(10) >= 9, ShouldBeShown = _random.Next(10) >= 7, - Vectors = Enumerable.Range(0, 128).Select(_ => (float)_random.NextDouble()).ToArray() + Vectors = Enumerable.Range(0, 128).Select(_ => (float)_random.NextDouble()).ToArray() }; if (_random.Next(10) >= 5) diff --git a/LiteDB.Benchmarks/Models/Generators/FileMetaGeneratorComponentModel.cs b/LiteDB.Benchmarks/Models/Generators/FileMetaGeneratorComponentModel.cs new file mode 100644 index 000000000..365d422cc --- /dev/null +++ b/LiteDB.Benchmarks/Models/Generators/FileMetaGeneratorComponentModel.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace LiteDB.Benchmarks.Models.Generators +{ + public static class FileMetaGeneratorComponentModel where T : FileMetaBaseComponentModel, new() + { + private static Random _random; + + private static T Generate() + { + var docGuid = Guid.NewGuid(); + + var generatedFileMeta = new T + { + FileId = docGuid, + Version = _random.Next(5), + Title = $"Document-{docGuid}", + MimeType = "application/pdf", + IsFavorite = _random.Next(10) >= 9, + ShouldBeShown = _random.Next(10) >= 7, + Vectors = Enumerable.Range(0, 128).Select(_ => (float)_random.NextDouble()).ToArray() + }; + + if (_random.Next(10) >= 5) + { + generatedFileMeta.ValidFrom = DateTimeOffset.Now.AddDays(-20 + _random.Next(40)); + generatedFileMeta.ValidFrom = DateTimeOffset.UtcNow.AddDays(-10 + _random.Next(40)); + } + + return generatedFileMeta; + } + + public static List GenerateList(int amountToGenerate) + { + _random = new Random(0); + + var generatedList = new List(); + for (var i = 0; i < amountToGenerate; i++) generatedList.Add(Generate()); + + foreach (var fileMeta in generatedList) + { + if (_random.Next(100) <= 1) + { + continue; + } + + fileMeta.ParentId = generatedList[_random.Next(amountToGenerate)].Id; + } + + return generatedList; + } + } +} \ No newline at end of file diff --git a/LiteDB.Tests/Mapper/CustomMapping_Tests.cs b/LiteDB.Tests/Mapper/CustomMapping_Tests.cs index 50b42d032..9c11d130f 100644 --- a/LiteDB.Tests/Mapper/CustomMapping_Tests.cs +++ b/LiteDB.Tests/Mapper/CustomMapping_Tests.cs @@ -1,67 +1,133 @@ -using System; -using System.Collections.Generic; -using FluentAssertions; -using Xunit; - -namespace LiteDB.Tests.Mapper -{ - public class CustomMappingCtor_Tests - { - public class UserWithCustomId - { - public int Key { get; } - public string Name { get; } - - public UserWithCustomId(int key, string name) - { - this.Key = key; - this.Name = name; - } - } - - [Fact] - public void Custom_Ctor_With_Custom_Id() - { - var mapper = new BsonMapper(); - - mapper.Entity() - .Id(u => u.Key, false); - - var doc = new BsonDocument { ["_id"] = 10, ["name"] = "John" }; - - var user = mapper.ToObject(doc); - - user.Key.Should().Be(10); // Expected user.Key to be 10, but found 0. - user.Name.Should().Be("John"); - } - - public abstract class BaseClass - { - [BsonId] - public string CustomId { get; set; } - - [BsonField("CustomName")] - public string Name { get; set; } - } - - public class ConcreteClass : BaseClass - { - - } - - [Fact] - public void Custom_Id_In_Interface() - { - var mapper = new BsonMapper(); - - var obj = new ConcreteClass { CustomId = "myid", Name = "myname" }; - var doc = mapper.Serialize(obj) as BsonDocument; - doc["_id"].Should().NotBeNull(); - doc["_id"].Should().Be("myid"); - doc["CustomName"].Should().NotBe(BsonValue.Null); - doc["CustomName"].Should().Be("myname"); - doc["Name"].Should().Be(BsonValue.Null); - doc.Keys.ExpectCount(2); - } - } +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using FluentAssertions; +using Xunit; + +namespace LiteDB.Tests.Mapper +{ + public class CustomMappingCtor_Tests + { + public class UserWithCustomId + { + public int Key { get; } + public string Name { get; } + + public UserWithCustomId(int key, string name) + { + this.Key = key; + this.Name = name; + } + } + + [Fact] + public void Custom_Ctor_With_Custom_Id() + { + var mapper = new BsonMapper(); + + mapper.Entity() + .Id(u => u.Key, false); + + var doc = new BsonDocument { ["_id"] = 10, ["name"] = "John" }; + + var user = mapper.ToObject(doc); + + user.Key.Should().Be(10); //     Expected user.Key to be 10, but found 0. +            user.Name.Should().Be("John"); + } + + public abstract class BaseClass + { + [BsonId] + public string CustomId { get; set; } + + [BsonField("CustomName")] + public string Name { get; set; } + } + + public class ConcreteClass : BaseClass + { + + } + + [Fact] + public void Custom_Id_In_Interface() + { + var mapper = new BsonMapper(); + + var obj = new ConcreteClass { CustomId = "myid", Name = "myname" }; + var doc = mapper.Serialize(obj) as BsonDocument; + doc["_id"].Should().NotBeNull(); + doc["_id"].Should().Be("myid"); + doc["CustomName"].Should().NotBe(BsonValue.Null); + doc["CustomName"].Should().Be("myname"); + doc["Name"].Should().Be(BsonValue.Null); + doc.Keys.ExpectCount(2); + } + + public class ClassWithBsonIgnore + { + public int Id { get; set; } + public string Keep { get; set; } + [BsonIgnore] + public string Ignore { get; set; } + } + + [Fact] + public void Test_BsonIgnoreAttribute() + { + var mapper = new BsonMapper(); + var obj = new ClassWithBsonIgnore { Id = 1, Keep = "K", Ignore = "I" }; + var doc = mapper.Serialize(obj) as BsonDocument; + + doc["_id"].Should().Be(1); + doc["Keep"].Should().Be("K"); + doc.ContainsKey("Ignore").Should().BeFalse(); + doc.Keys.ExpectCount(2); + } + +#if NET8_0_OR_GREATER + + public class ClassWithKeyAttribute + { + [Key] + public int MyKey { get; set; } + public string Value { get; set; } + } + + [Fact] + public void Test_KeyAttribute_As_BsonId() + { + var mapper = new BsonMapper(); + var obj = new ClassWithKeyAttribute { MyKey = 123, Value = "abc" }; + var doc = mapper.Serialize(obj) as BsonDocument; + + doc["_id"].Should().Be(123); + doc["Value"].Should().Be("abc"); + doc.Keys.ExpectCount(2); + } + + public class ClassWithNotMappedAttribute + { + public int Id { get; set; } + public string Keep { get; set; } + [NotMapped] + public string Ignore { get; set; } + } + + [Fact] + public void Test_NotMappedAttribute_As_BsonIgnore() + { + var mapper = new BsonMapper(); + var obj = new ClassWithNotMappedAttribute { Id = 1, Keep = "K", Ignore = "I" }; + var doc = mapper.Serialize(obj) as BsonDocument; + + doc["_id"].Should().Be(1); + doc["Keep"].Should().Be("K"); + doc.ContainsKey("Ignore").Should().BeFalse(); + doc.Keys.ExpectCount(2); + } +#endif + } } \ No newline at end of file diff --git a/LiteDB.sln b/LiteDB.sln index 7f0051124..6fdae1ec1 100644 --- a/LiteDB.sln +++ b/LiteDB.sln @@ -1,182 +1,230 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32328.378 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB", "LiteDB\LiteDB.csproj", "{9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Tests", "LiteDB.Tests\LiteDB.Tests.csproj", "{74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Shell", "LiteDB.Shell\LiteDB.Shell.csproj", "{99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Benchmarks", "LiteDB.Benchmarks\LiteDB.Benchmarks.csproj", "{DF9C82C1-446F-458A-AA50-78E58BA17273}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Stress", "LiteDB.Stress\LiteDB.Stress.csproj", "{FFBC5669-DA32-4907-8793-7B414279DA3B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.Demo.Tools.VectorSearch", "LiteDB.Demo.Tools.VectorSearch\LiteDB.Demo.Tools.VectorSearch.csproj", "{64EEF08C-CE83-4929-B5E4-583BBC332941}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{E8763934-E46A-4AAF-A2B5-E812016DAF84}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Issue_2586_RollbackTransaction", "LiteDB.ReproRunner\Repros\Issue_2586_RollbackTransaction\Issue_2586_RollbackTransaction.csproj", "{BE1D6CA2-134A-404A-8F1A-C48E4E240159}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{D455AC29-7847-4DF4-AD06-69042F8B8885}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LiteDB.ReproRunner", "LiteDB.ReproRunner", "{C172DFBD-9BFC-41A4-82B9-5B9BBC90850D}" - ProjectSection(SolutionItems) = preProject - LiteDB.ReproRunner\README.md = LiteDB.ReproRunner\README.md - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.ReproRunner.Cli", "LiteDB.ReproRunner\LiteDB.ReproRunner.Cli\LiteDB.ReproRunner.Cli.csproj", "{CDCF5EED-50F3-4790-B180-10B203EE6B4B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repros", "Repros", "{B0BD59D3-0D10-42BF-A744-533473577C8C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Issue_2561_TransactionMonitor", "LiteDB.ReproRunner\Repros\Issue_2561_TransactionMonitor\Issue_2561_TransactionMonitor.csproj", "{B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3B786621-2B82-4C69-8FE9-3889ECB36E75}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.ReproRunner.Tests", "LiteDB.ReproRunner.Tests\LiteDB.ReproRunner.Tests.csproj", "{3EF8E506-B57B-4A98-AD09-E687F9DC515D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.ReproRunner.Shared", "LiteDB.ReproRunner\LiteDB.ReproRunner.Shared\LiteDB.ReproRunner.Shared.csproj", "{CE109129-4017-46E7-BE84-17D4D83296F4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedMutexHarness", "LiteDB.Tests.SharedMutexHarness\SharedMutexHarness.csproj", "{F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x64.ActiveCfg = Debug|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x64.Build.0 = Debug|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x86.ActiveCfg = Debug|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x86.Build.0 = Debug|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|Any CPU.Build.0 = Release|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x64.ActiveCfg = Release|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x64.Build.0 = Release|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x86.ActiveCfg = Release|Any CPU - {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x86.Build.0 = Release|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x64.ActiveCfg = Debug|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x64.Build.0 = Debug|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x86.ActiveCfg = Debug|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x86.Build.0 = Debug|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|Any CPU.Build.0 = Release|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x64.ActiveCfg = Release|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x64.Build.0 = Release|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x86.ActiveCfg = Release|Any CPU - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x86.Build.0 = Release|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x64.ActiveCfg = Debug|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x64.Build.0 = Debug|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x86.ActiveCfg = Debug|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x86.Build.0 = Debug|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|Any CPU.Build.0 = Release|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x64.ActiveCfg = Release|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x64.Build.0 = Release|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x86.ActiveCfg = Release|Any CPU - {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x86.Build.0 = Release|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x64.ActiveCfg = Debug|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x64.Build.0 = Debug|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x86.ActiveCfg = Debug|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x86.Build.0 = Debug|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|Any CPU.Build.0 = Release|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x64.ActiveCfg = Release|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x64.Build.0 = Release|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x86.ActiveCfg = Release|Any CPU - {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x86.Build.0 = Release|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x64.ActiveCfg = Debug|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x64.Build.0 = Debug|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x86.ActiveCfg = Debug|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x86.Build.0 = Debug|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|Any CPU.Build.0 = Release|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x64.ActiveCfg = Release|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x64.Build.0 = Release|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x86.ActiveCfg = Release|Any CPU - {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x86.Build.0 = Release|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|Any CPU.Build.0 = Debug|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x64.ActiveCfg = Debug|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x64.Build.0 = Debug|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x86.ActiveCfg = Debug|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x86.Build.0 = Debug|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|Any CPU.ActiveCfg = Release|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|Any CPU.Build.0 = Release|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x64.ActiveCfg = Release|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x64.Build.0 = Release|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x86.ActiveCfg = Release|Any CPU - {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x86.Build.0 = Release|Any CPU - {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|Any CPU.Build.0 = Release|Any CPU - {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|Any CPU.Build.0 = Release|Any CPU - {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|Any CPU.Build.0 = Release|Any CPU - {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|Any CPU.Build.0 = Release|Any CPU - {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|Any CPU.Build.0 = Release|Any CPU - {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|Any CPU.Build.0 = Release|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x64.ActiveCfg = Debug|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x64.Build.0 = Debug|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x86.ActiveCfg = Debug|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x86.Build.0 = Debug|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|Any CPU.Build.0 = Release|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x64.ActiveCfg = Release|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x64.Build.0 = Release|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x86.ActiveCfg = Release|Any CPU - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {45099B85-2AE1-434B-913A-6AD14FD3AF4A} - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {E8763934-E46A-4AAF-A2B5-E812016DAF84} = {D455AC29-7847-4DF4-AD06-69042F8B8885} - {CDCF5EED-50F3-4790-B180-10B203EE6B4B} = {C172DFBD-9BFC-41A4-82B9-5B9BBC90850D} - {B0BD59D3-0D10-42BF-A744-533473577C8C} = {C172DFBD-9BFC-41A4-82B9-5B9BBC90850D} - {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC} = {B0BD59D3-0D10-42BF-A744-533473577C8C} - {3EF8E506-B57B-4A98-AD09-E687F9DC515D} = {3B786621-2B82-4C69-8FE9-3889ECB36E75} - {CE109129-4017-46E7-BE84-17D4D83296F4} = {C172DFBD-9BFC-41A4-82B9-5B9BBC90850D} - {BE1D6CA2-134A-404A-8F1A-C48E4E240159} = {B0BD59D3-0D10-42BF-A744-533473577C8C} - {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA} = {3B786621-2B82-4C69-8FE9-3889ECB36E75} - {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6} = {3B786621-2B82-4C69-8FE9-3889ECB36E75} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32328.378 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB", "LiteDB\LiteDB.csproj", "{9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Tests", "LiteDB.Tests\LiteDB.Tests.csproj", "{74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Shell", "LiteDB.Shell\LiteDB.Shell.csproj", "{99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Benchmarks", "LiteDB.Benchmarks\LiteDB.Benchmarks.csproj", "{DF9C82C1-446F-458A-AA50-78E58BA17273}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiteDB.Stress", "LiteDB.Stress\LiteDB.Stress.csproj", "{FFBC5669-DA32-4907-8793-7B414279DA3B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.Demo.Tools.VectorSearch", "LiteDB.Demo.Tools.VectorSearch\LiteDB.Demo.Tools.VectorSearch.csproj", "{64EEF08C-CE83-4929-B5E4-583BBC332941}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{E8763934-E46A-4AAF-A2B5-E812016DAF84}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Issue_2586_RollbackTransaction", "LiteDB.ReproRunner\Repros\Issue_2586_RollbackTransaction\Issue_2586_RollbackTransaction.csproj", "{BE1D6CA2-134A-404A-8F1A-C48E4E240159}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{D455AC29-7847-4DF4-AD06-69042F8B8885}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LiteDB.ReproRunner", "LiteDB.ReproRunner", "{C172DFBD-9BFC-41A4-82B9-5B9BBC90850D}" + ProjectSection(SolutionItems) = preProject + LiteDB.ReproRunner\README.md = LiteDB.ReproRunner\README.md + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.ReproRunner.Cli", "LiteDB.ReproRunner\LiteDB.ReproRunner.Cli\LiteDB.ReproRunner.Cli.csproj", "{CDCF5EED-50F3-4790-B180-10B203EE6B4B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repros", "Repros", "{B0BD59D3-0D10-42BF-A744-533473577C8C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Issue_2561_TransactionMonitor", "LiteDB.ReproRunner\Repros\Issue_2561_TransactionMonitor\Issue_2561_TransactionMonitor.csproj", "{B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3B786621-2B82-4C69-8FE9-3889ECB36E75}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.ReproRunner.Tests", "LiteDB.ReproRunner.Tests\LiteDB.ReproRunner.Tests.csproj", "{3EF8E506-B57B-4A98-AD09-E687F9DC515D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiteDB.ReproRunner.Shared", "LiteDB.ReproRunner\LiteDB.ReproRunner.Shared\LiteDB.ReproRunner.Shared.csproj", "{CE109129-4017-46E7-BE84-17D4D83296F4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedMutexHarness", "LiteDB.Tests.SharedMutexHarness\SharedMutexHarness.csproj", "{F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x64.ActiveCfg = Debug|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x64.Build.0 = Debug|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x86.ActiveCfg = Debug|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Debug|x86.Build.0 = Debug|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|Any CPU.Build.0 = Release|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x64.ActiveCfg = Release|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x64.Build.0 = Release|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x86.ActiveCfg = Release|Any CPU + {9497DA19-1FCA-4C2E-A1AB-8DFAACBC76E1}.Release|x86.Build.0 = Release|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x64.ActiveCfg = Debug|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x64.Build.0 = Debug|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x86.ActiveCfg = Debug|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Debug|x86.Build.0 = Debug|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|Any CPU.Build.0 = Release|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x64.ActiveCfg = Release|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x64.Build.0 = Release|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x86.ActiveCfg = Release|Any CPU + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA}.Release|x86.Build.0 = Release|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x64.ActiveCfg = Debug|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x64.Build.0 = Debug|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x86.ActiveCfg = Debug|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Debug|x86.Build.0 = Debug|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|Any CPU.Build.0 = Release|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x64.ActiveCfg = Release|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x64.Build.0 = Release|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x86.ActiveCfg = Release|Any CPU + {99887C89-CAE4-4A8D-AC4B-87E28B9B1F87}.Release|x86.Build.0 = Release|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x64.ActiveCfg = Debug|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x64.Build.0 = Debug|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x86.ActiveCfg = Debug|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Debug|x86.Build.0 = Debug|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|Any CPU.Build.0 = Release|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x64.ActiveCfg = Release|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x64.Build.0 = Release|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x86.ActiveCfg = Release|Any CPU + {DF9C82C1-446F-458A-AA50-78E58BA17273}.Release|x86.Build.0 = Release|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x64.ActiveCfg = Debug|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x64.Build.0 = Debug|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x86.ActiveCfg = Debug|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Debug|x86.Build.0 = Debug|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|Any CPU.Build.0 = Release|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x64.ActiveCfg = Release|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x64.Build.0 = Release|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x86.ActiveCfg = Release|Any CPU + {FFBC5669-DA32-4907-8793-7B414279DA3B}.Release|x86.Build.0 = Release|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x64.ActiveCfg = Debug|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x64.Build.0 = Debug|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x86.ActiveCfg = Debug|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Debug|x86.Build.0 = Debug|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|Any CPU.Build.0 = Release|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x64.ActiveCfg = Release|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x64.Build.0 = Release|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x86.ActiveCfg = Release|Any CPU + {64EEF08C-CE83-4929-B5E4-583BBC332941}.Release|x86.Build.0 = Release|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|x64.ActiveCfg = Debug|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|x64.Build.0 = Debug|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|x86.ActiveCfg = Debug|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Debug|x86.Build.0 = Debug|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|Any CPU.Build.0 = Release|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|x64.ActiveCfg = Release|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|x64.Build.0 = Release|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|x86.ActiveCfg = Release|Any CPU + {E8763934-E46A-4AAF-A2B5-E812016DAF84}.Release|x86.Build.0 = Release|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|x64.ActiveCfg = Debug|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|x64.Build.0 = Debug|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|x86.ActiveCfg = Debug|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Debug|x86.Build.0 = Debug|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|Any CPU.Build.0 = Release|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|x64.ActiveCfg = Release|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|x64.Build.0 = Release|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|x86.ActiveCfg = Release|Any CPU + {BE1D6CA2-134A-404A-8F1A-C48E4E240159}.Release|x86.Build.0 = Release|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|x64.ActiveCfg = Debug|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|x64.Build.0 = Debug|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|x86.ActiveCfg = Debug|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Debug|x86.Build.0 = Debug|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|Any CPU.Build.0 = Release|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|x64.ActiveCfg = Release|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|x64.Build.0 = Release|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|x86.ActiveCfg = Release|Any CPU + {CDCF5EED-50F3-4790-B180-10B203EE6B4B}.Release|x86.Build.0 = Release|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|x64.ActiveCfg = Debug|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|x64.Build.0 = Debug|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|x86.ActiveCfg = Debug|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Debug|x86.Build.0 = Debug|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|Any CPU.Build.0 = Release|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|x64.ActiveCfg = Release|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|x64.Build.0 = Release|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|x86.ActiveCfg = Release|Any CPU + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC}.Release|x86.Build.0 = Release|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|x64.ActiveCfg = Debug|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|x64.Build.0 = Debug|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|x86.ActiveCfg = Debug|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Debug|x86.Build.0 = Debug|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|Any CPU.Build.0 = Release|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|x64.ActiveCfg = Release|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|x64.Build.0 = Release|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|x86.ActiveCfg = Release|Any CPU + {3EF8E506-B57B-4A98-AD09-E687F9DC515D}.Release|x86.Build.0 = Release|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|x64.ActiveCfg = Debug|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|x64.Build.0 = Debug|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|x86.ActiveCfg = Debug|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Debug|x86.Build.0 = Debug|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|Any CPU.Build.0 = Release|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|x64.ActiveCfg = Release|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|x64.Build.0 = Release|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|x86.ActiveCfg = Release|Any CPU + {CE109129-4017-46E7-BE84-17D4D83296F4}.Release|x86.Build.0 = Release|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x64.ActiveCfg = Debug|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x64.Build.0 = Debug|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x86.ActiveCfg = Debug|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Debug|x86.Build.0 = Debug|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|Any CPU.Build.0 = Release|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x64.ActiveCfg = Release|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x64.Build.0 = Release|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x86.ActiveCfg = Release|Any CPU + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {74E32E43-2A57-4A38-BD8C-9108B0DCAEAA} = {3B786621-2B82-4C69-8FE9-3889ECB36E75} + {E8763934-E46A-4AAF-A2B5-E812016DAF84} = {D455AC29-7847-4DF4-AD06-69042F8B8885} + {BE1D6CA2-134A-404A-8F1A-C48E4E240159} = {B0BD59D3-0D10-42BF-A744-533473577C8C} + {CDCF5EED-50F3-4790-B180-10B203EE6B4B} = {C172DFBD-9BFC-41A4-82B9-5B9BBC90850D} + {B0BD59D3-0D10-42BF-A744-533473577C8C} = {C172DFBD-9BFC-41A4-82B9-5B9BBC90850D} + {B5BF3DFE-5F26-447A-AF5A-60C6E3D341AC} = {B0BD59D3-0D10-42BF-A744-533473577C8C} + {3EF8E506-B57B-4A98-AD09-E687F9DC515D} = {3B786621-2B82-4C69-8FE9-3889ECB36E75} + {CE109129-4017-46E7-BE84-17D4D83296F4} = {C172DFBD-9BFC-41A4-82B9-5B9BBC90850D} + {F7E423B9-B90B-4F4D-B02A-F0101BBA26E6} = {3B786621-2B82-4C69-8FE9-3889ECB36E75} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {45099B85-2AE1-434B-913A-6AD14FD3AF4A} + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection +EndGlobal diff --git a/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs b/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs index e3b122088..8b03918ed 100644 --- a/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs +++ b/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs @@ -1,6 +1,10 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +#if NET8_0_OR_GREATER +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +#endif using System.Linq; using System.Reflection; using System.Threading; @@ -57,9 +61,15 @@ internal EntityMapper GetEntityMapper(Type type) /// Returns an EntityMapper from each requested Type /// protected void BuildEntityMapper(EntityMapper mapper) - { - var idAttr = typeof(BsonIdAttribute); - var ignoreAttr = typeof(BsonIgnoreAttribute); + { +#if NET8_0_OR_GREATER + var idAttrs = new List { typeof(BsonIdAttribute), typeof(KeyAttribute) }; + var ignoreAttrs = new List { typeof(BsonIgnoreAttribute), typeof(NotMappedAttribute) }; +#else + // in netstandard2.0 KeyAttribute and NotMappedAttribute are not available without adding extra dependencies + var idAttrs = new List { typeof(BsonIdAttribute) }; + var ignoreAttrs = new List { typeof(BsonIgnoreAttribute) }; +#endif var fieldAttr = typeof(BsonFieldAttribute); var dbrefAttr = typeof(BsonRefAttribute); @@ -69,7 +79,7 @@ protected void BuildEntityMapper(EntityMapper mapper) foreach (var memberInfo in members) { // checks [BsonIgnore] - if (CustomAttributeExtensions.IsDefined(memberInfo, ignoreAttr, true)) continue; + if (ignoreAttrs.Any(ia => CustomAttributeExtensions.IsDefined(memberInfo, ia, true))) continue; // checks field name conversion var name = this.ResolveFieldName(memberInfo.Name); @@ -95,8 +105,25 @@ protected void BuildEntityMapper(EntityMapper mapper) var setter = Reflection.CreateGenericSetter(mapper.ForType, memberInfo); // check if property has [BsonId] to get with was setted AutoId = true - var autoId = (BsonIdAttribute)CustomAttributeExtensions.GetCustomAttributes(memberInfo, idAttr, true) - .FirstOrDefault(); + bool autoId = true; + foreach (var idAttr in idAttrs) + { + var identifierAttribute = CustomAttributeExtensions.GetCustomAttributes(memberInfo, idAttr, true) + .FirstOrDefault(); + + if(identifierAttribute is BsonIdAttribute bsonIdAttribute) + { + autoId = bsonIdAttribute.AutoId; + break; + } +#if NET8_0_OR_GREATER + if(identifierAttribute is KeyAttribute) + { + autoId = false; + break; + } +#endif + } // get data type var dataType = memberInfo is PropertyInfo @@ -109,7 +136,7 @@ protected void BuildEntityMapper(EntityMapper mapper) // create a property mapper var member = new MemberMapper { - AutoId = autoId == null ? true : autoId.AutoId, + AutoId = autoId, FieldName = name, MemberName = memberInfo.Name, DataType = dataType, @@ -148,10 +175,14 @@ protected void BuildEntityMapper(EntityMapper mapper) /// protected virtual MemberInfo GetIdMember(IEnumerable members) { + // check for [Key] attribute as well in .NET 8 or greater return Reflection.SelectMember(members, - x => CustomAttributeExtensions.IsDefined(x, typeof(BsonIdAttribute), true), + x => CustomAttributeExtensions.IsDefined(x, typeof(BsonIdAttribute), true), +#if NET8_0_OR_GREATER + x => CustomAttributeExtensions.IsDefined(x, typeof(KeyAttribute), true), +#endif x => x.Name.Equals("Id", StringComparison.OrdinalIgnoreCase), - x => x.Name.Equals(x.DeclaringType.Name + "Id", StringComparison.OrdinalIgnoreCase)); + x => x.Name.Equals(x.DeclaringType.Name + "Id", StringComparison.OrdinalIgnoreCase)); } /// diff --git a/README.md b/README.md index f3f780e82..3d0a3dcff 100644 --- a/README.md +++ b/README.md @@ -8,40 +8,43 @@ LiteDB is a small, fast and lightweight .NET NoSQL embedded database. -- Serverless NoSQL Document Store -- Simple API, similar to MongoDB -- 100% C# code for .NET 4.5 / NETStandard 1.3/2.0 in a single DLL (less than 450kb) -- Thread-safe -- ACID with full transaction support -- Data recovery after write failure (WAL log file) -- Datafile encryption using DES (AES) cryptography -- Map your POCO classes to `BsonDocument` using attributes or fluent mapper API -- Store files and stream data (like GridFS in MongoDB) -- Single data file storage (like SQLite) -- Index document fields for fast search -- LINQ support for queries -- SQL-Like commands to access/transform data -- [LiteDB Studio](https://github.com/mbdavid/LiteDB.Studio) - Nice UI for data access -- Open source and free for everyone - including commercial use -- Install from NuGet: `Install-Package LiteDB` - +* Serverless NoSQL Document Store +* Simple API, similar to MongoDB +* 100% C# code for .NET 4.5 / NETStandard 1.3/2.0 in a single DLL (less than 450kb) +* Thread-safe +* ACID with full transaction support +* Data recovery after write failure (WAL log file) +* Datafile encryption using DES (AES) cryptography +* Map your POCO classes to `BsonDocument` using attributes (like `[BsonId]`, `[Key]`, `[BsonIgnore]`, `[NotMapped]`) or fluent mapper API +* Store files and stream data (like GridFS in MongoDB) +* Single data file storage (like SQLite) +* Index document fields for fast search +* LINQ support for queries +* SQL-Like commands to access/transform data +* [LiteDB Studio](https://github.com/mbdavid/LiteDB.Studio) - Nice UI for data access +* Open source and free for everyone - including commercial use +* Install from NuGet: `Install-Package LiteDB` + + +## New v6 + +* Added support for DataAnnotations attributes ([Key] and [NotMapped]) as aliases for [BsonId] and [BsonIgnore] (for .NET 8+). ## New v5 -- New storage engine -- No locks for `read` operations (multiple readers) -- `Write` locks per collection (multiple writers) -- Internal/System collections -- New `SQL-Like Syntax` -- New query engine (support projection, sort, filter, query) -- Partial document load (root level) -- and much, much more! +* New storage engine +* No locks for `read` operations (multiple readers) +* `Write` locks per collection (multiple writers) +* Internal/System collections +* New `SQL-Like Syntax` +* New query engine (support projection, sort, filter, query) +* Partial document load (root level) +* and much, much more! ## Lite.Studio New UI to manage and visualize your database: - ![LiteDB.Studio](https://www.litedb.org/images/banner.gif) ## Documentation @@ -68,16 +71,16 @@ public class Customer } // Open database (or create if doesn't exist) -using(var db = new LiteDatabase(@"MyData.db")) +using(var db = new LiteDatabase(@""MyData.db"")) { // Get customer collection - var col = db.GetCollection("customers"); + var col = db.GetCollection(""customers""); // Create your new customer instance var customer = new Customer { - Name = "John Doe", - Phones = new string[] { "8000-0000", "9000-0000" }, + Name = ""John Doe"", + Phones = new string[] { ""8000-0000"", ""9000-0000"" }, Age = 39, IsActive = true }; @@ -89,7 +92,7 @@ using(var db = new LiteDatabase(@"MyData.db")) col.Insert(customer); // Update a document inside a collection - customer.Name = "Joana Doe"; + customer.Name = ""Joana Doe""; col.Update(customer); @@ -114,15 +117,15 @@ public class Order // Re-use mapper from global instance var mapper = BsonMapper.Global; -// "Products" and "Customer" are from other collections (not embedded document) +// ""Products"" and ""Customer"" are from other collections (not embedded document) mapper.Entity() - .DbRef(x => x.Customer, "customers") // 1 to 1/0 reference - .DbRef(x => x.Products, "products") // 1 to Many reference - .Field(x => x.ShippingAddress, "addr"); // Embedded sub document + .DbRef(x => x.Customer, ""customers"") // 1 to 1/0 reference + .DbRef(x => x.Products, ""products"") // 1 to Many reference + .Field(x => x.ShippingAddress, ""addr""); // Embedded sub document -using(var db = new LiteDatabase("MyOrderDatafile.db")) +using(var db = new LiteDatabase(""MyOrderDatafile.db"")) { - var orders = db.GetCollection("orders"); + var orders = db.GetCollection(""orders""); // When query Order, includes references var query = orders @@ -142,21 +145,21 @@ using(var db = new LiteDatabase("MyOrderDatafile.db")) ## Where to use? -- Desktop/local small applications -- Application file format -- Small web sites/applications -- One database **per account/user** data store +* Desktop/local small applications +* Application file format +* Small web sites/applications +* One database **per account/user** data store ## Plugins -- A GUI viewer tool: https://github.com/falahati/LiteDBViewer (v4) -- A GUI editor tool: https://github.com/JosefNemec/LiteDbExplorer (v4) -- Lucene.NET directory: https://github.com/sheryever/LiteDBDirectory -- LINQPad support: https://github.com/adospace/litedbpad -- F# Support: https://github.com/Zaid-Ajaj/LiteDB.FSharp (v4) -- UltraLiteDB (for Unity or IOT): https://github.com/rejemy/UltraLiteDB -- OneBella - cross platform (windows, macos, linux) GUI tool : https://github.com/namigop/OneBella -- LiteDB.Migration: Framework that makes schema migrations easier: https://github.com/JKamsker/LiteDB.Migration/ +* A GUI viewer tool: https://github.com/falahati/LiteDBViewer (v4) +* A GUI editor tool: https://github.com/JosefNemec/LiteDbExplorer (v4) +* Lucene.NET directory: https://github.com/sheryever/LiteDBDirectory +* LINQPad support: https://github.com/adospace/litedbpad +* F# Support: https://github.com/Zaid-Ajaj/LiteDB.FSharp (v4) +* UltraLiteDB (for Unity or IOT): https://github.com/rejemy/UltraLiteDB +* OneBella - cross platform (windows, macos, linux) GUI tool : https://github.com/namigop/OneBella +* LiteDB.Migration: Framework that makes schema migrations easier: https://github.com/JKamsker/LiteDB.Migration/ ## Changelog @@ -166,6 +169,6 @@ Change details for each release are documented in the [release notes](https://gi LiteDB is digitally signed courtesy of [SignPath](https://www.signpath.io) - - + + \ No newline at end of file From 77811ffa30d7f9b8530b6fa60839e8eb35feccf2 Mon Sep 17 00:00:00 2001 From: Nataraja Date: Sun, 2 Nov 2025 16:02:29 +0100 Subject: [PATCH 2/4] Update LiteDB.Tests/Mapper/CustomMapping_Tests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- LiteDB.Tests/Mapper/CustomMapping_Tests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteDB.Tests/Mapper/CustomMapping_Tests.cs b/LiteDB.Tests/Mapper/CustomMapping_Tests.cs index 9c11d130f..a1bb41888 100644 --- a/LiteDB.Tests/Mapper/CustomMapping_Tests.cs +++ b/LiteDB.Tests/Mapper/CustomMapping_Tests.cs @@ -33,7 +33,7 @@ public void Custom_Ctor_With_Custom_Id() var user = mapper.ToObject(doc); - user.Key.Should().Be(10); //     Expected user.Key to be 10, but found 0. + user.Key.Should().Be(10); // Ensure that the custom mapping sets the Key property from the _id field.             user.Name.Should().Be("John"); } From 2f5b5d25c06009668f44afb584a0d13b101039bc Mon Sep 17 00:00:00 2001 From: Nataraja Date: Sun, 2 Nov 2025 16:02:40 +0100 Subject: [PATCH 3/4] Update LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Mapper/BsonMapper.GetEntityMapper.cs | 556 +++++++++--------- 1 file changed, 278 insertions(+), 278 deletions(-) diff --git a/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs b/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs index 8b03918ed..5cf26def1 100644 --- a/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs +++ b/LiteDB/Client/Mapper/BsonMapper.GetEntityMapper.cs @@ -1,284 +1,284 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -#if NET8_0_OR_GREATER -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -#endif -using System.Linq; -using System.Reflection; -using System.Threading; - -namespace LiteDB; - -public partial class BsonMapper -{ - /// - /// Mapping cache between Class/BsonDocument - /// - private readonly ConcurrentDictionary _entities = new(); - - /// - /// Get property mapper between typed .NET class and BsonDocument - Cache results - /// - internal EntityMapper GetEntityMapper(Type type) - { - if (_entities.TryGetValue(type, out EntityMapper mapper)) - { - return mapper; - } - - using var cts = new CancellationTokenSource(); - try - { - // We need to add the empty shell, because ``BuildEntityMapper`` may use this method recursively - var newMapper = new EntityMapper(type, cts.Token); - mapper = _entities.GetOrAdd(type, newMapper); - if (ReferenceEquals(mapper, newMapper)) - { - try - { - this.BuildEntityMapper(mapper); - } - catch (Exception ex) - { - _entities.TryRemove(type, out _); - throw new LiteException(LiteException.MAPPING_ERROR, $"Error in '{type.Name}' mapping: {ex.Message}", ex); - } - } - } - finally - { - // Allow the Mapper to be used for de-/serialization - cts.Cancel(); - } - - return mapper; - } - - /// - /// Use this method to override how your class can be, by default, mapped from entity to Bson document. - /// Returns an EntityMapper from each requested Type - /// - protected void BuildEntityMapper(EntityMapper mapper) +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +#if NET8_0_OR_GREATER +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +#endif +using System.Linq; +using System.Reflection; +using System.Threading; + +namespace LiteDB; + +public partial class BsonMapper +{ + /// + /// Mapping cache between Class/BsonDocument + /// + private readonly ConcurrentDictionary _entities = new(); + + /// + /// Get property mapper between typed .NET class and BsonDocument - Cache results + /// + internal EntityMapper GetEntityMapper(Type type) { -#if NET8_0_OR_GREATER - var idAttrs = new List { typeof(BsonIdAttribute), typeof(KeyAttribute) }; - var ignoreAttrs = new List { typeof(BsonIgnoreAttribute), typeof(NotMappedAttribute) }; -#else - // in netstandard2.0 KeyAttribute and NotMappedAttribute are not available without adding extra dependencies - var idAttrs = new List { typeof(BsonIdAttribute) }; - var ignoreAttrs = new List { typeof(BsonIgnoreAttribute) }; -#endif - var fieldAttr = typeof(BsonFieldAttribute); - var dbrefAttr = typeof(BsonRefAttribute); - - var members = this.GetTypeMembers(mapper.ForType); - var id = this.GetIdMember(members); - - foreach (var memberInfo in members) - { - // checks [BsonIgnore] - if (ignoreAttrs.Any(ia => CustomAttributeExtensions.IsDefined(memberInfo, ia, true))) continue; - - // checks field name conversion - var name = this.ResolveFieldName(memberInfo.Name); - - // check if property has [BsonField] - var field = (BsonFieldAttribute)CustomAttributeExtensions.GetCustomAttributes(memberInfo, fieldAttr, true) - .FirstOrDefault(); - - // check if property has [BsonField] with a custom field name - if (field != null && field.Name != null) - { - name = field.Name; - } - - // checks if memberInfo is id field - if (memberInfo == id) - { - name = "_id"; - } - - // create getter/setter function - var getter = Reflection.CreateGenericGetter(mapper.ForType, memberInfo); - var setter = Reflection.CreateGenericSetter(mapper.ForType, memberInfo); - - // check if property has [BsonId] to get with was setted AutoId = true - bool autoId = true; - foreach (var idAttr in idAttrs) - { - var identifierAttribute = CustomAttributeExtensions.GetCustomAttributes(memberInfo, idAttr, true) - .FirstOrDefault(); - - if(identifierAttribute is BsonIdAttribute bsonIdAttribute) - { - autoId = bsonIdAttribute.AutoId; - break; + if (_entities.TryGetValue(type, out EntityMapper mapper)) + { + return mapper; + } + + using var cts = new CancellationTokenSource(); + try + { + // We need to add the empty shell, because ``BuildEntityMapper`` may use this method recursively + var newMapper = new EntityMapper(type, cts.Token); + mapper = _entities.GetOrAdd(type, newMapper); + if (ReferenceEquals(mapper, newMapper)) + { + try + { + this.BuildEntityMapper(mapper); } -#if NET8_0_OR_GREATER - if(identifierAttribute is KeyAttribute) - { - autoId = false; - break; + catch (Exception ex) + { + _entities.TryRemove(type, out _); + throw new LiteException(LiteException.MAPPING_ERROR, $"Error in '{type.Name}' mapping: {ex.Message}", ex); } -#endif - } - - // get data type - var dataType = memberInfo is PropertyInfo - ? (memberInfo as PropertyInfo).PropertyType - : (memberInfo as FieldInfo).FieldType; - - // check if datatype is list/array - var isEnumerable = Reflection.IsEnumerable(dataType); - - // create a property mapper - var member = new MemberMapper - { - AutoId = autoId, - FieldName = name, - MemberName = memberInfo.Name, - DataType = dataType, - IsEnumerable = isEnumerable, - UnderlyingType = isEnumerable ? Reflection.GetListItemType(dataType) : dataType, - Getter = getter, - Setter = setter - }; - - // check if property has [BsonRef] - var dbRef = (BsonRefAttribute)CustomAttributeExtensions.GetCustomAttributes(memberInfo, dbrefAttr, false) - .FirstOrDefault(); - - if (dbRef != null && memberInfo is PropertyInfo) - { - BsonMapper.RegisterDbRef(this, member, _typeNameBinder, - dbRef.Collection ?? this.ResolveCollectionName((memberInfo as PropertyInfo).PropertyType)); - } - - // support callback to user modify member mapper - this.ResolveMember?.Invoke(mapper.ForType, memberInfo, member); - - // test if has name and there is no duplicate field - // when member is not ignore - if (member.FieldName != null && - mapper.Members.Any(x => x.FieldName.Equals(name, StringComparison.OrdinalIgnoreCase)) == false && - !member.IsIgnore) - { - mapper.Members.Add(member); - } - } - } - - /// - /// Gets MemberInfo that refers to Id from a document object. - /// - protected virtual MemberInfo GetIdMember(IEnumerable members) - { - // check for [Key] attribute as well in .NET 8 or greater - return Reflection.SelectMember(members, + } + } + finally + { + // Allow the Mapper to be used for de-/serialization + cts.Cancel(); + } + + return mapper; + } + + /// + /// Use this method to override how your class can be, by default, mapped from entity to Bson document. + /// Returns an EntityMapper from each requested Type + /// + protected void BuildEntityMapper(EntityMapper mapper) + { +#if NET8_0_OR_GREATER + var idAttrs = new List { typeof(BsonIdAttribute), typeof(KeyAttribute) }; + var ignoreAttrs = new List { typeof(BsonIgnoreAttribute), typeof(NotMappedAttribute) }; +#else + // in netstandard2.0 KeyAttribute and NotMappedAttribute are not available without adding extra dependencies + var idAttrs = new List { typeof(BsonIdAttribute) }; + var ignoreAttrs = new List { typeof(BsonIgnoreAttribute) }; +#endif + var fieldAttr = typeof(BsonFieldAttribute); + var dbrefAttr = typeof(BsonRefAttribute); + + var members = this.GetTypeMembers(mapper.ForType); + var id = this.GetIdMember(members); + + foreach (var memberInfo in members) + { + // checks [BsonIgnore] + if (ignoreAttrs.Any(ia => CustomAttributeExtensions.IsDefined(memberInfo, ia, true))) continue; + + // checks field name conversion + var name = this.ResolveFieldName(memberInfo.Name); + + // check if property has [BsonField] + var field = (BsonFieldAttribute)CustomAttributeExtensions.GetCustomAttributes(memberInfo, fieldAttr, true) + .FirstOrDefault(); + + // check if property has [BsonField] with a custom field name + if (field != null && field.Name != null) + { + name = field.Name; + } + + // checks if memberInfo is id field + if (memberInfo == id) + { + name = "_id"; + } + + // create getter/setter function + var getter = Reflection.CreateGenericGetter(mapper.ForType, memberInfo); + var setter = Reflection.CreateGenericSetter(mapper.ForType, memberInfo); + + // check if property has [BsonId] to get with was setted AutoId = true + // BsonIdAttribute takes precedence over KeyAttribute if both are present + bool autoId = true; + var bsonIdAttribute = (BsonIdAttribute)CustomAttributeExtensions.GetCustomAttributes(memberInfo, typeof(BsonIdAttribute), true) + .FirstOrDefault(); + if (bsonIdAttribute != null) + { + autoId = bsonIdAttribute.AutoId; + } +#if NET8_0_OR_GREATER + else + { + var keyAttribute = (KeyAttribute)CustomAttributeExtensions.GetCustomAttributes(memberInfo, typeof(KeyAttribute), true) + .FirstOrDefault(); + if (keyAttribute != null) + { + autoId = false; + } + } +#endif + + // get data type + var dataType = memberInfo is PropertyInfo + ? (memberInfo as PropertyInfo).PropertyType + : (memberInfo as FieldInfo).FieldType; + + // check if datatype is list/array + var isEnumerable = Reflection.IsEnumerable(dataType); + + // create a property mapper + var member = new MemberMapper + { + AutoId = autoId, + FieldName = name, + MemberName = memberInfo.Name, + DataType = dataType, + IsEnumerable = isEnumerable, + UnderlyingType = isEnumerable ? Reflection.GetListItemType(dataType) : dataType, + Getter = getter, + Setter = setter + }; + + // check if property has [BsonRef] + var dbRef = (BsonRefAttribute)CustomAttributeExtensions.GetCustomAttributes(memberInfo, dbrefAttr, false) + .FirstOrDefault(); + + if (dbRef != null && memberInfo is PropertyInfo) + { + BsonMapper.RegisterDbRef(this, member, _typeNameBinder, + dbRef.Collection ?? this.ResolveCollectionName((memberInfo as PropertyInfo).PropertyType)); + } + + // support callback to user modify member mapper + this.ResolveMember?.Invoke(mapper.ForType, memberInfo, member); + + // test if has name and there is no duplicate field + // when member is not ignore + if (member.FieldName != null && + mapper.Members.Any(x => x.FieldName.Equals(name, StringComparison.OrdinalIgnoreCase)) == false && + !member.IsIgnore) + { + mapper.Members.Add(member); + } + } + } + + /// + /// Gets MemberInfo that refers to Id from a document object. + /// + protected virtual MemberInfo GetIdMember(IEnumerable members) + { + // check for [Key] attribute as well in .NET 8 or greater + return Reflection.SelectMember(members, x => CustomAttributeExtensions.IsDefined(x, typeof(BsonIdAttribute), true), -#if NET8_0_OR_GREATER - x => CustomAttributeExtensions.IsDefined(x, typeof(KeyAttribute), true), -#endif - x => x.Name.Equals("Id", StringComparison.OrdinalIgnoreCase), +#if NET8_0_OR_GREATER + x => CustomAttributeExtensions.IsDefined(x, typeof(KeyAttribute), true), +#endif + x => x.Name.Equals("Id", StringComparison.OrdinalIgnoreCase), x => x.Name.Equals(x.DeclaringType.Name + "Id", StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Returns all member that will be have mapper between POCO class to document - /// - protected virtual IEnumerable GetTypeMembers(Type type) - { - var members = new List(); - - var flags = this.IncludeNonPublic - ? (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) - : (BindingFlags.Public | BindingFlags.Instance); - - members.AddRange(type.GetProperties(flags) - .Where(x => x.CanRead && x.GetIndexParameters().Length == 0) - .Select(x => x as MemberInfo)); - - var shouldIncludeFields = members.Count == 0 - && type.GetTypeInfo().IsValueType; - - if (shouldIncludeFields || this.IncludeFields) - { - members.AddRange(type.GetFields(flags).Where(x => !x.Name.EndsWith("k__BackingField") && x.IsStatic == false) - .Select(x => x as MemberInfo)); - } - - return members; - } - - /// - /// Get best construtor to use to initialize this entity. - /// - Look if contains [BsonCtor] attribute - /// - Look for parameterless ctor - /// - Look for first contructor with parameter and use BsonDocument to send RawValue - /// - protected virtual CreateObject GetTypeCtor(EntityMapper mapper) - { - Type type = mapper.ForType; - List Mappings = new List(); - bool returnZeroParamNull = false; - foreach (ConstructorInfo ctor in type.GetConstructors()) - { - ParameterInfo[] pars = ctor.GetParameters(); - // For 0 parameters, we can let the Reflection.CreateInstance handle it, unless they've specified a [BsonCtor] attribute on a different constructor. - if (pars.Length == 0) - { - returnZeroParamNull = true; - continue; - } - - KeyValuePair[] paramMap = new KeyValuePair[pars.Length]; - int i; - for (i = 0; i < pars.Length; i++) - { - ParameterInfo par = pars[i]; - MemberMapper mi = null; - foreach (MemberMapper member in mapper.Members) - { - if (member.MemberName.ToLower() == par.Name.ToLower() && member.DataType == par.ParameterType) - { - mi = member; - break; - } - } - - if (mi == null) - { - break; - } - - paramMap[i] = new KeyValuePair(mi.FieldName, mi.DataType); - } - - if (i < pars.Length) - { - continue; - } - - CreateObject toAdd = (BsonDocument value) => - Activator.CreateInstance(type, paramMap.Select(x => - this.Deserialize(x.Value, value[x.Key])).ToArray()); - if (ctor.GetCustomAttribute() != null) - { - return toAdd; - } - else - { - Mappings.Add(toAdd); - } - } - - if (returnZeroParamNull) - { - return null; - } - - return Mappings.FirstOrDefault(); - } + } + + /// + /// Returns all member that will be have mapper between POCO class to document + /// + protected virtual IEnumerable GetTypeMembers(Type type) + { + var members = new List(); + + var flags = this.IncludeNonPublic + ? (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) + : (BindingFlags.Public | BindingFlags.Instance); + + members.AddRange(type.GetProperties(flags) + .Where(x => x.CanRead && x.GetIndexParameters().Length == 0) + .Select(x => x as MemberInfo)); + + var shouldIncludeFields = members.Count == 0 + && type.GetTypeInfo().IsValueType; + + if (shouldIncludeFields || this.IncludeFields) + { + members.AddRange(type.GetFields(flags).Where(x => !x.Name.EndsWith("k__BackingField") && x.IsStatic == false) + .Select(x => x as MemberInfo)); + } + + return members; + } + + /// + /// Get best construtor to use to initialize this entity. + /// - Look if contains [BsonCtor] attribute + /// - Look for parameterless ctor + /// - Look for first contructor with parameter and use BsonDocument to send RawValue + /// + protected virtual CreateObject GetTypeCtor(EntityMapper mapper) + { + Type type = mapper.ForType; + List Mappings = new List(); + bool returnZeroParamNull = false; + foreach (ConstructorInfo ctor in type.GetConstructors()) + { + ParameterInfo[] pars = ctor.GetParameters(); + // For 0 parameters, we can let the Reflection.CreateInstance handle it, unless they've specified a [BsonCtor] attribute on a different constructor. + if (pars.Length == 0) + { + returnZeroParamNull = true; + continue; + } + + KeyValuePair[] paramMap = new KeyValuePair[pars.Length]; + int i; + for (i = 0; i < pars.Length; i++) + { + ParameterInfo par = pars[i]; + MemberMapper mi = null; + foreach (MemberMapper member in mapper.Members) + { + if (member.MemberName.ToLower() == par.Name.ToLower() && member.DataType == par.ParameterType) + { + mi = member; + break; + } + } + + if (mi == null) + { + break; + } + + paramMap[i] = new KeyValuePair(mi.FieldName, mi.DataType); + } + + if (i < pars.Length) + { + continue; + } + + CreateObject toAdd = (BsonDocument value) => + Activator.CreateInstance(type, paramMap.Select(x => + this.Deserialize(x.Value, value[x.Key])).ToArray()); + if (ctor.GetCustomAttribute() != null) + { + return toAdd; + } + else + { + Mappings.Add(toAdd); + } + } + + if (returnZeroParamNull) + { + return null; + } + + return Mappings.FirstOrDefault(); + } } \ No newline at end of file From 736e08704caed875e0679cdf31a1e7d5ec57e192 Mon Sep 17 00:00:00 2001 From: Luca Fabbri Date: Mon, 3 Nov 2025 09:47:26 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 99 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 3d0a3dcff..5d0fc9b6f 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,22 @@ LiteDB is a small, fast and lightweight .NET NoSQL embedded database. -* Serverless NoSQL Document Store -* Simple API, similar to MongoDB -* 100% C# code for .NET 4.5 / NETStandard 1.3/2.0 in a single DLL (less than 450kb) -* Thread-safe -* ACID with full transaction support -* Data recovery after write failure (WAL log file) -* Datafile encryption using DES (AES) cryptography -* Map your POCO classes to `BsonDocument` using attributes (like `[BsonId]`, `[Key]`, `[BsonIgnore]`, `[NotMapped]`) or fluent mapper API -* Store files and stream data (like GridFS in MongoDB) -* Single data file storage (like SQLite) -* Index document fields for fast search -* LINQ support for queries -* SQL-Like commands to access/transform data -* [LiteDB Studio](https://github.com/mbdavid/LiteDB.Studio) - Nice UI for data access -* Open source and free for everyone - including commercial use -* Install from NuGet: `Install-Package LiteDB` +- Serverless NoSQL Document Store +- Simple API, similar to MongoDB +- 100% C# code for .NET 4.5 / NETStandard 1.3/2.0 in a single DLL (less than 450kb) +- Thread-safe +- ACID with full transaction support +- Data recovery after write failure (WAL log file) +- Datafile encryption using DES (AES) cryptography +- Map your POCO classes to `BsonDocument` using attributes or fluent mapper API +- Store files and stream data (like GridFS in MongoDB) +- Single data file storage (like SQLite) +- Index document fields for fast search +- LINQ support for queries +- SQL-Like commands to access/transform data +- [LiteDB Studio](https://github.com/mbdavid/LiteDB.Studio) - Nice UI for data access +- Open source and free for everyone - including commercial use +- Install from NuGet: `Install-Package LiteDB` ## New v6 @@ -32,19 +32,20 @@ LiteDB is a small, fast and lightweight .NET NoSQL embedded database. ## New v5 -* New storage engine -* No locks for `read` operations (multiple readers) -* `Write` locks per collection (multiple writers) -* Internal/System collections -* New `SQL-Like Syntax` -* New query engine (support projection, sort, filter, query) -* Partial document load (root level) -* and much, much more! +- New storage engine +- No locks for `read` operations (multiple readers) +- `Write` locks per collection (multiple writers) +- Internal/System collections +- New `SQL-Like Syntax` +- New query engine (support projection, sort, filter, query) +- Partial document load (root level) +- and much, much more! ## Lite.Studio New UI to manage and visualize your database: + ![LiteDB.Studio](https://www.litedb.org/images/banner.gif) ## Documentation @@ -71,16 +72,16 @@ public class Customer } // Open database (or create if doesn't exist) -using(var db = new LiteDatabase(@""MyData.db"")) +using(var db = new LiteDatabase(@"MyData.db")) { // Get customer collection - var col = db.GetCollection(""customers""); + var col = db.GetCollection("customers"); // Create your new customer instance var customer = new Customer { - Name = ""John Doe"", - Phones = new string[] { ""8000-0000"", ""9000-0000"" }, + Name = "John Doe", + Phones = new string[] { "8000-0000", "9000-0000" }, Age = 39, IsActive = true }; @@ -92,7 +93,7 @@ using(var db = new LiteDatabase(@""MyData.db"")) col.Insert(customer); // Update a document inside a collection - customer.Name = ""Joana Doe""; + customer.Name = "Joana Doe"; col.Update(customer); @@ -117,15 +118,15 @@ public class Order // Re-use mapper from global instance var mapper = BsonMapper.Global; -// ""Products"" and ""Customer"" are from other collections (not embedded document) +// "Products" and "Customer" are from other collections (not embedded document) mapper.Entity() - .DbRef(x => x.Customer, ""customers"") // 1 to 1/0 reference - .DbRef(x => x.Products, ""products"") // 1 to Many reference - .Field(x => x.ShippingAddress, ""addr""); // Embedded sub document + .DbRef(x => x.Customer, "customers") // 1 to 1/0 reference + .DbRef(x => x.Products, "products") // 1 to Many reference + .Field(x => x.ShippingAddress, "addr"); // Embedded sub document -using(var db = new LiteDatabase(""MyOrderDatafile.db"")) +using(var db = new LiteDatabase("MyOrderDatafile.db")) { - var orders = db.GetCollection(""orders""); + var orders = db.GetCollection("orders"); // When query Order, includes references var query = orders @@ -145,21 +146,21 @@ using(var db = new LiteDatabase(""MyOrderDatafile.db"")) ## Where to use? -* Desktop/local small applications -* Application file format -* Small web sites/applications -* One database **per account/user** data store +- Desktop/local small applications +- Application file format +- Small web sites/applications +- One database **per account/user** data store ## Plugins -* A GUI viewer tool: https://github.com/falahati/LiteDBViewer (v4) -* A GUI editor tool: https://github.com/JosefNemec/LiteDbExplorer (v4) -* Lucene.NET directory: https://github.com/sheryever/LiteDBDirectory -* LINQPad support: https://github.com/adospace/litedbpad -* F# Support: https://github.com/Zaid-Ajaj/LiteDB.FSharp (v4) -* UltraLiteDB (for Unity or IOT): https://github.com/rejemy/UltraLiteDB -* OneBella - cross platform (windows, macos, linux) GUI tool : https://github.com/namigop/OneBella -* LiteDB.Migration: Framework that makes schema migrations easier: https://github.com/JKamsker/LiteDB.Migration/ +- A GUI viewer tool: https://github.com/falahati/LiteDBViewer (v4) +- A GUI editor tool: https://github.com/JosefNemec/LiteDbExplorer (v4) +- Lucene.NET directory: https://github.com/sheryever/LiteDBDirectory +- LINQPad support: https://github.com/adospace/litedbpad +- F# Support: https://github.com/Zaid-Ajaj/LiteDB.FSharp (v4) +- UltraLiteDB (for Unity or IOT): https://github.com/rejemy/UltraLiteDB +- OneBella - cross platform (windows, macos, linux) GUI tool : https://github.com/namigop/OneBella +- LiteDB.Migration: Framework that makes schema migrations easier: https://github.com/JKamsker/LiteDB.Migration/ ## Changelog @@ -169,6 +170,6 @@ Change details for each release are documented in the [release notes](https://gi LiteDB is digitally signed courtesy of [SignPath](https://www.signpath.io) - - + + \ No newline at end of file