diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 672b15d3ddf0..96f27f73c88e 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -155,6 +155,7 @@
+
diff --git a/dotnet/SK-dotnet.slnx b/dotnet/SK-dotnet.slnx
index 687e09529260..1b95d7421e07 100644
--- a/dotnet/SK-dotnet.slnx
+++ b/dotnet/SK-dotnet.slnx
@@ -149,6 +149,7 @@
+
@@ -324,6 +325,7 @@
+
diff --git a/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj b/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj
index 5c1fc5edb9cc..36707e4dd0fb 100644
--- a/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj
+++ b/dotnet/samples/GettingStartedWithVectorStores/GettingStartedWithVectorStores.csproj
@@ -42,6 +42,7 @@
+
diff --git a/dotnet/samples/GettingStartedWithVectorStores/README.md b/dotnet/samples/GettingStartedWithVectorStores/README.md
index 36efdea60e78..4e72b84346dd 100644
--- a/dotnet/samples/GettingStartedWithVectorStores/README.md
+++ b/dotnet/samples/GettingStartedWithVectorStores/README.md
@@ -4,6 +4,10 @@ This project contains a step by step guide to get started using Vector Stores wi
The examples can be run as integration tests but their code can also be copied to stand-alone programs.
+## Step 5 — LiteDB advanced scenario
+
+`Step5_LiteDb_AdvancedScenario` shows how to combine transactional batch upserts, per-property embedding generators and metrics, and the extended filter surface (`Contains`, `StartsWith`, `EndsWith`, `IN`) when working with the LiteDB connector.
+
## Configuring Secrets
Most of the examples will require secrets and credentials, to access OpenAI, Azure OpenAI,
diff --git a/dotnet/samples/GettingStartedWithVectorStores/Step5_LiteDb_AdvancedScenario.cs b/dotnet/samples/GettingStartedWithVectorStores/Step5_LiteDb_AdvancedScenario.cs
new file mode 100644
index 000000000000..77232318c6c2
--- /dev/null
+++ b/dotnet/samples/GettingStartedWithVectorStores/Step5_LiteDb_AdvancedScenario.cs
@@ -0,0 +1,173 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.VectorData;
+using Microsoft.SemanticKernel.Connectors.LiteDb;
+
+namespace GettingStartedWithVectorStores;
+
+///
+/// Demonstrates advanced LiteDB usage: per-property generators and metrics, transactional batch upserts, and expressive filters.
+///
+public sealed class Step5_LiteDb_AdvancedScenario(ITestOutputHelper output) : BaseTest(output)
+{
+ private static readonly string[] FilterCities = new[] { "Seattle", "Portland" };
+
+ [Fact]
+ public async Task RunEndToEndScenarioAsync()
+ {
+ var services = new ServiceCollection();
+ services.AddSingleton>>(new SampleEmbeddingGenerator("store"));
+ services.AddLiteDbVectorStore(_ => new LiteDbVectorStoreOptions
+ {
+ DisposeDatabase = false,
+ DistanceMetric = LiteDbDistanceMetric.Cosine,
+ AutoCreateVectorIndexes = true,
+ CollectionNamePrefix = "sample_"
+ });
+ services.AddLiteDbCollection("hotels", _ => new VectorStoreCollectionDefinition
+ {
+ Properties =
+ {
+ new VectorStoreKeyProperty(nameof(SampleHotel.HotelId), typeof(string)),
+ new VectorStoreDataProperty(nameof(SampleHotel.City), typeof(string)),
+ new VectorStoreDataProperty(nameof(SampleHotel.Tags), typeof(List)),
+ new VectorStoreDataProperty(nameof(SampleHotel.Description), typeof(string)),
+ new VectorStoreVectorProperty(nameof(SampleHotel.Overview), typeof(string), 3)
+ {
+ DistanceFunction = DistanceFunction.DotProductSimilarity,
+ EmbeddingGenerator = new SampleEmbeddingGenerator("overview")
+ },
+ new VectorStoreVectorProperty(nameof(SampleHotel.Amenities), typeof(string), 3)
+ {
+ DistanceFunction = DistanceFunction.EuclideanDistance,
+ EmbeddingGenerator = new SampleEmbeddingGenerator("amenities")
+ }
+ }
+ });
+
+ using var provider = services.BuildServiceProvider();
+ var collection = provider.GetRequiredService>();
+ await collection.EnsureCollectionExistsAsync();
+
+ var hotels = new[]
+ {
+ new SampleHotel
+ {
+ HotelId = "alpha",
+ City = "Seattle",
+ Description = "Waterfront spa resort",
+ Tags = new List { "spa", "rooftop" },
+ Overview = "0.9,0.05,0.05",
+ Amenities = "0.2,0.5,0.3"
+ },
+ new SampleHotel
+ {
+ HotelId = "beta",
+ City = "Portland",
+ Description = "Modern downtown escape",
+ Tags = new List { "boutique", "spa" },
+ Overview = "0.7,0.1,0.2",
+ Amenities = "0.6,0.2,0.2"
+ },
+ new SampleHotel
+ {
+ HotelId = "gamma",
+ City = "San Francisco",
+ Description = "Historic harbor view",
+ Tags = new List { "historic", "view" },
+ Overview = "0.1,0.8,0.1",
+ Amenities = "0.3,0.1,0.6"
+ }
+ };
+
+ // Batch upsert executes inside a transaction – either all records are stored or none are.
+ await collection.UpsertAsync(hotels);
+
+#pragma warning disable CA1866 // the literal "t" is clearer for sample filtering.
+ var searchOptions = new VectorSearchOptions
+ {
+ VectorProperty = h => h.Overview,
+ Filter = h => (h.Tags.Contains("spa") || h.City!.StartsWith("Sea"))
+ && FilterCities.Contains(h.City!)
+ && h.Description!.EndsWith("t"),
+ IncludeVectors = false
+ };
+#pragma warning restore CA1866
+
+ var results = await collection.SearchAsync("0.8,0.1,0.1", top: 2, searchOptions).ToListAsync();
+
+ foreach (var result in results)
+ {
+ this.WriteLine($"Hotel: {result.Record.HotelId} in {result.Record.City} (score {result.Score:F3})");
+ }
+
+ Assert.Single(results);
+ Assert.Equal("alpha", results[0].Record.HotelId);
+ }
+
+ private sealed class SampleHotel
+ {
+ [VectorStoreKey]
+ public string? HotelId { get; set; }
+
+ [VectorStoreData]
+ public string? City { get; set; }
+
+ [VectorStoreData]
+ public string? Description { get; set; }
+
+ [VectorStoreData]
+ public List Tags { get; set; } = new();
+
+ [VectorStoreVector(Dimensions: 3)]
+ public string? Overview { get; set; }
+
+ [VectorStoreVector(Dimensions: 3)]
+ public string? Amenities { get; set; }
+ }
+
+ private sealed class SampleEmbeddingGenerator(string tag) : IEmbeddingGenerator>
+ {
+ public Task>> GenerateAsync(IEnumerable values, EmbeddingGenerationOptions? options = null, CancellationToken cancellationToken = default)
+ {
+ var embeddings = new GeneratedEmbeddings>();
+ foreach (var value in values)
+ {
+ embeddings.Add(new Embedding(ParseVector(value, tag)));
+ }
+
+ return Task.FromResult(embeddings);
+ }
+
+ public Task> GenerateAsync(string value, EmbeddingGenerationOptions? options = null, CancellationToken cancellationToken = default)
+ => Task.FromResult(new Embedding(ParseVector(value, tag)));
+
+ public object? GetService(Type serviceType, object? serviceKey = null)
+ => null;
+
+ public void Dispose()
+ {
+ }
+
+ private static float[] ParseVector(string value, string tagPrefix)
+ {
+ var values = value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
+ .Select(float.Parse)
+ .ToArray();
+
+ // Different prefixes allow callers to verify generator precedence in diagnostics.
+ return tagPrefix switch
+ {
+ "overview" => values,
+ _ => values.Select(v => Math.Clamp(v + 0.05f, 0f, 1f)).ToArray()
+ };
+ }
+ }
+}
diff --git a/dotnet/src/VectorData/LiteDb/LiteDb.csproj b/dotnet/src/VectorData/LiteDb/LiteDb.csproj
new file mode 100644
index 000000000000..1a7714e9cf51
--- /dev/null
+++ b/dotnet/src/VectorData/LiteDb/LiteDb.csproj
@@ -0,0 +1,37 @@
+
+
+
+ Microsoft.SemanticKernel.Connectors.LiteDb
+ $(AssemblyName)
+ net8.0;netstandard2.1
+ preview
+
+
+
+
+
+ LiteDB provider for Microsoft.Extensions.VectorData
+ LiteDB provider for Microsoft.Extensions.VectorData by Semantic Kernel
+ VECTORDATA-CONNECTORS-NUGET.md
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/src/VectorData/LiteDb/LiteDbCollection.cs b/dotnet/src/VectorData/LiteDb/LiteDbCollection.cs
new file mode 100644
index 000000000000..60a6fd90cc23
--- /dev/null
+++ b/dotnet/src/VectorData/LiteDb/LiteDbCollection.cs
@@ -0,0 +1,404 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading;
+using System.Threading.Tasks;
+using LiteDB;
+using LiteDB.Vector;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.VectorData;
+using Microsoft.Extensions.VectorData.ProviderServices;
+
+namespace Microsoft.SemanticKernel.Connectors.LiteDb;
+
+#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
+///
+/// Service for storing and retrieving vector records backed by LiteDB.
+///
+/// The data type of the record key.
+/// The record data model used when interacting with the collection.
+public class LiteDbCollection : VectorStoreCollection
+ where TKey : notnull
+ where TRecord : class
+#pragma warning restore CA1711
+{
+ private readonly LiteDatabase _database;
+ private readonly ILiteCollection _collection;
+ private readonly CollectionModel _model;
+ private readonly LiteDbMapper _mapper;
+ private readonly LiteDbFilterTranslator _filterTranslator = new();
+ private readonly LiteDbVectorStoreOptions _storeOptions;
+ private readonly LiteDbCollectionOptions _options;
+ private readonly VectorStoreCollectionMetadata _collectionMetadata;
+ private readonly IReadOnlyList _vectorProperties;
+ private readonly LiteDbDistanceMetric _defaultMetric;
+
+ ///
+ public override string Name { get; }
+
+ internal LiteDbCollection(
+ LiteDatabase database,
+ string name,
+ LiteDbVectorStoreOptions storeOptions,
+ LiteDbCollectionOptions? options,
+ Func modelFactory,
+ string connectionIdentifier)
+ {
+ ArgumentNullException.ThrowIfNull(database);
+ ArgumentNullException.ThrowIfNull(storeOptions);
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ throw new ArgumentException("Collection name cannot be null or whitespace.", nameof(name));
+ }
+
+ this._database = database;
+ this.Name = name;
+ this._storeOptions = storeOptions;
+ this._options = options ?? LiteDbCollectionOptions.Default;
+
+ this._model = modelFactory(this._options);
+ if (typeof(TKey) != typeof(string) && typeof(TKey) != typeof(object))
+ {
+ throw new NotSupportedException("LiteDB connector currently supports string keys.");
+ }
+
+ this._collection = this._database.GetCollection(name);
+ this._mapper = new LiteDbMapper(this._model);
+ this._vectorProperties = this._model.VectorProperties;
+ this._defaultMetric = this._options.DistanceMetric ?? storeOptions.DistanceMetric;
+
+ this._collectionMetadata = new()
+ {
+ VectorStoreSystemName = LiteDbConstants.VectorStoreSystemName,
+ VectorStoreName = connectionIdentifier,
+ CollectionName = name
+ };
+ }
+
+ ///
+ public override Task CollectionExistsAsync(CancellationToken cancellationToken = default)
+ {
+ var names = this._database.GetCollectionNames();
+ var exists = names.Contains(this.Name, StringComparer.OrdinalIgnoreCase);
+ return Task.FromResult(exists);
+ }
+
+ ///
+ public override Task EnsureCollectionExistsAsync(CancellationToken cancellationToken = default)
+ {
+ if (this._storeOptions.AutoEnsureVectorIndex && this._vectorProperties.Count > 0)
+ {
+ foreach (var vectorProperty in this._vectorProperties)
+ {
+ var dimensions = this._options.VectorDimensions ?? vectorProperty.Dimensions;
+ if (dimensions <= 0)
+ {
+ throw new InvalidOperationException($"Vector property '{vectorProperty.ModelName}' must specify dimensions when creating a LiteDB collection.");
+ }
+
+ var metric = ResolveMetric(vectorProperty.DistanceFunction, this._options.DistanceMetric ?? this._defaultMetric);
+ var path = BsonExpression.Create($"$.{vectorProperty.StorageName}");
+ var indexOptions = new VectorIndexOptions((ushort)dimensions, MapMetric(metric));
+ this._collection.EnsureIndex(vectorProperty.StorageName, path, indexOptions);
+ }
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ public override Task EnsureCollectionDeletedAsync(CancellationToken cancellationToken = default)
+ {
+ this._database.DropCollection(this.Name);
+ return Task.CompletedTask;
+ }
+
+ ///
+ public override Task GetAsync(TKey key, RecordRetrievalOptions? options = default, CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(key);
+ options ??= new RecordRetrievalOptions();
+
+ if (options.IncludeVectors && this._model.EmbeddingGenerationRequired)
+ {
+ throw new NotSupportedException(VectorDataStrings.IncludeVectorsNotSupportedWithEmbeddingGeneration);
+ }
+
+ var bsonKey = new BsonValue(key);
+ var document = this._collection.FindById(bsonKey);
+ if (document is null)
+ {
+ return Task.FromResult(null);
+ }
+
+ var record = this._mapper.MapToRecord(document, options.IncludeVectors);
+ return Task.FromResult(record);
+ }
+
+ ///
+ public override Task DeleteAsync(TKey key, CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(key);
+ this._collection.Delete(new BsonValue(key));
+ return Task.CompletedTask;
+ }
+
+ ///
+ public override Task UpsertAsync(TRecord record, CancellationToken cancellationToken = default)
+ => this.UpsertAsync([record], cancellationToken);
+
+ ///
+ public override async Task UpsertAsync(IEnumerable records, CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(records);
+
+ var materialized = records as IList ?? records.ToList();
+ if (materialized.Count == 0)
+ {
+ return;
+ }
+
+ IReadOnlyDictionary>? generatedVectors = null;
+ if (this._model.EmbeddingGenerationRequired)
+ {
+ generatedVectors = await this.GenerateEmbeddingsAsync(materialized, cancellationToken).ConfigureAwait(false);
+ }
+
+ var documents = new List(materialized.Count);
+ for (var i = 0; i < materialized.Count; i++)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ var document = this._mapper.MapToDocument(materialized[i], generatedVectors, i);
+ this.ValidateVectorDimensions(document);
+ documents.Add(document);
+ }
+
+ if (documents.Count == 1)
+ {
+ this._collection.Upsert(documents[0]);
+ return;
+ }
+
+ var startedTransaction = this._database.BeginTrans();
+ try
+ {
+ this._collection.Upsert(documents);
+ if (startedTransaction)
+ {
+ this._database.Commit();
+ }
+ }
+ catch
+ {
+ if (startedTransaction)
+ {
+ this._database.Rollback();
+ }
+
+ throw;
+ }
+ }
+
+ ///
+ public override IAsyncEnumerable GetAsync(Expression> filter, int top, FilteredRecordRetrievalOptions? options = null, CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(filter);
+ if (top <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(top));
+ }
+
+ options ??= new FilteredRecordRetrievalOptions();
+ if (options.IncludeVectors && this._model.EmbeddingGenerationRequired)
+ {
+ throw new NotSupportedException(VectorDataStrings.IncludeVectorsNotSupportedWithEmbeddingGeneration);
+ }
+
+ return this.ExecuteQueryAsync(filter, top, options, cancellationToken);
+ }
+
+ private async IAsyncEnumerable ExecuteQueryAsync(Expression> filter, int top, FilteredRecordRetrievalOptions options, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken)
+ {
+ var query = this._collection.Query();
+ var (expression, parameters) = this._filterTranslator.Translate(filter, this._model);
+ query = query.Where(expression, parameters);
+
+ var result = query.Limit(top + options.Skip);
+ if (options.Skip > 0)
+ {
+ result = result.Skip(options.Skip);
+ }
+
+ foreach (var document in result.ToEnumerable())
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ yield return this._mapper.MapToRecord(document, options.IncludeVectors);
+ }
+ }
+
+ ///
+ public override async IAsyncEnumerable> SearchAsync(TInput searchValue, int top, VectorSearchOptions? options = null, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ if (top < 1)
+ {
+ throw new ArgumentOutOfRangeException(nameof(top));
+ }
+ options ??= new VectorSearchOptions();
+
+ if (options.IncludeVectors && this._model.EmbeddingGenerationRequired)
+ {
+ throw new NotSupportedException(VectorDataStrings.IncludeVectorsNotSupportedWithEmbeddingGeneration);
+ }
+
+ var vectorProperty = this._model.GetVectorPropertyOrSingle(options);
+ var searchVector = await this.ResolveSearchVectorAsync(searchValue, vectorProperty, cancellationToken).ConfigureAwait(false);
+
+ if (searchVector.Length == 0)
+ {
+ yield break;
+ }
+
+ var metric = ResolveMetric(vectorProperty.DistanceFunction, this._options.DistanceMetric ?? this._defaultMetric);
+ var query = this._collection.Query();
+
+ if (options.Filter is not null)
+ {
+ var (expression, parameters) = this._filterTranslator.Translate(options.Filter, this._model);
+ query = query.Where(expression, parameters);
+ }
+
+ var vectorArray = searchVector.ToArray();
+ var take = top + options.Skip;
+ var results = query.TopKNear($"$.{vectorProperty.StorageName}", vectorArray, take).ToEnumerable();
+
+ var index = 0;
+
+ foreach (var document in results)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ if (index++ < options.Skip)
+ {
+ continue;
+ }
+ var record = this._mapper.MapToRecord(document, options.IncludeVectors);
+
+ if (!document.TryGetValue(vectorProperty.StorageName, out var value) || value is not BsonVector candidate)
+ {
+ continue;
+ }
+
+ var score = LiteDbVectorMath.Compare(vectorArray, candidate.Values, metric);
+ yield return new VectorSearchResult(record, score);
+ }
+ }
+
+ ///
+ public override object? GetService(Type serviceType, object? serviceKey = null)
+ {
+ ArgumentNullException.ThrowIfNull(serviceType);
+
+ return serviceKey is not null
+ ? null
+ : serviceType == typeof(VectorStoreCollectionMetadata)
+ ? this._collectionMetadata
+ : serviceType.IsInstanceOfType(this)
+ ? this
+ : null;
+ }
+
+ private async Task>?> GenerateEmbeddingsAsync(IList records, CancellationToken cancellationToken)
+ {
+ if (this._vectorProperties.Count == 0)
+ {
+ return null;
+ }
+
+ Dictionary>? generated = null;
+
+ foreach (var property in this._vectorProperties)
+ {
+ var existingValue = property.GetValueAsObject(records[0]);
+ if (existingValue is not null && LiteDbMapper.TryConvertVector(existingValue, out _))
+ {
+ continue;
+ }
+
+ if (property.TryGenerateEmbeddings>(records, cancellationToken, out var task))
+ {
+ var embeddings = (IReadOnlyList>)await task.ConfigureAwait(false);
+ generated ??= new Dictionary>(StringComparer.Ordinal);
+ generated[property.ModelName] = embeddings.Select(e => e.Vector.ToArray()).ToList();
+ }
+ else
+ {
+ throw new InvalidOperationException(VectorDataStrings.IncompatibleEmbeddingGeneratorWasConfiguredForInputType(typeof(TRecord), property.EmbeddingGenerator?.GetType() ?? typeof(object)));
+ }
+ }
+
+ return generated;
+ }
+
+ private async Task> ResolveSearchVectorAsync(TInput value, VectorPropertyModel property, CancellationToken cancellationToken)
+ {
+ switch (value)
+ {
+ case ReadOnlyMemory memory:
+ return memory;
+ case float[] array:
+ return new ReadOnlyMemory(array);
+ case Embedding embedding:
+ return embedding.Vector;
+ default:
+ if (property.EmbeddingGenerator is IEmbeddingGenerator> generator)
+ {
+ return await generator.GenerateVectorAsync(value, cancellationToken: cancellationToken).ConfigureAwait(false);
+ }
+
+ throw new NotSupportedException(VectorDataStrings.InvalidSearchInputAndNoEmbeddingGeneratorWasConfigured(value?.GetType() ?? typeof(object), LiteDbModelBuilder.SupportedVectorTypes));
+ }
+ }
+
+ private static LiteDbDistanceMetric ResolveMetric(string? distanceFunction, LiteDbDistanceMetric fallback)
+ => distanceFunction switch
+ {
+ DistanceFunction.CosineSimilarity => LiteDbDistanceMetric.Cosine,
+ DistanceFunction.CosineDistance => LiteDbDistanceMetric.Cosine,
+ DistanceFunction.DotProductSimilarity => LiteDbDistanceMetric.DotProduct,
+ DistanceFunction.EuclideanDistance => LiteDbDistanceMetric.Euclidean,
+ _ => fallback
+ };
+
+ private static VectorDistanceMetric MapMetric(LiteDbDistanceMetric metric)
+ => metric switch
+ {
+ LiteDbDistanceMetric.Cosine => VectorDistanceMetric.Cosine,
+ LiteDbDistanceMetric.DotProduct => VectorDistanceMetric.DotProduct,
+ LiteDbDistanceMetric.Euclidean => VectorDistanceMetric.Euclidean,
+ _ => throw new NotSupportedException($"Unsupported distance metric '{metric}'.")
+ };
+
+ private void ValidateVectorDimensions(BsonDocument document)
+ {
+ foreach (var property in this._vectorProperties)
+ {
+ if (!document.TryGetValue(property.StorageName, out var value) || value is not BsonVector vector)
+ {
+ continue;
+ }
+
+ var expectedDimensions = this._options.VectorDimensions ?? property.Dimensions;
+ if (expectedDimensions <= 0)
+ {
+ continue;
+ }
+
+ if (vector.Values.Length != expectedDimensions)
+ {
+ throw new InvalidOperationException($"Vector property '{property.ModelName}' expects {expectedDimensions} dimensions but received {vector.Values.Length}.");
+ }
+ }
+ }
+}
diff --git a/dotnet/src/VectorData/LiteDb/LiteDbCollectionOptions.cs b/dotnet/src/VectorData/LiteDb/LiteDbCollectionOptions.cs
new file mode 100644
index 000000000000..9ed37a9abf11
--- /dev/null
+++ b/dotnet/src/VectorData/LiteDb/LiteDbCollectionOptions.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using LiteDB;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.VectorData;
+
+namespace Microsoft.SemanticKernel.Connectors.LiteDb;
+
+///
+/// Options for configuring a LiteDB vector collection.
+///
+public sealed class LiteDbCollectionOptions
+{
+ internal static readonly LiteDbCollectionOptions Default = new();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public LiteDbCollectionOptions()
+ {
+ }
+
+ internal LiteDbCollectionOptions(LiteDbCollectionOptions? source)
+ {
+ if (source is null)
+ {
+ return;
+ }
+
+ this.Definition = source.Definition;
+ this.EmbeddingGenerator = source.EmbeddingGenerator;
+ this.VectorDimensions = source.VectorDimensions;
+ this.DistanceMetric = source.DistanceMetric;
+ this.ConnectionString = source.ConnectionString;
+ this.CollectionNamePrefix = source.CollectionNamePrefix;
+ }
+
+ ///
+ /// Gets or sets the schema definition for dynamic collections.
+ ///
+ public VectorStoreCollectionDefinition? Definition { get; set; }
+
+ ///
+ /// Gets or sets the embedding generator used to populate vector properties for this collection.
+ ///
+ public IEmbeddingGenerator? EmbeddingGenerator { get; set; }
+
+ ///
+ /// Gets or sets the dimensionality of the stored vectors.
+ ///
+ public int? VectorDimensions { get; set; }
+
+ ///
+ /// Gets or sets the distance metric to use for the vector index.
+ ///
+ public LiteDbDistanceMetric? DistanceMetric { get; set; }
+
+ ///
+ /// Gets or sets the LiteDB connection string override.
+ ///
+ public string? ConnectionString { get; set; }
+
+ ///
+ /// Gets or sets the collection name prefix applied when creating tables.
+ ///
+ public string? CollectionNamePrefix { get; set; }
+}
diff --git a/dotnet/src/VectorData/LiteDb/LiteDbConstants.cs b/dotnet/src/VectorData/LiteDb/LiteDbConstants.cs
new file mode 100644
index 000000000000..e0de736d0ae6
--- /dev/null
+++ b/dotnet/src/VectorData/LiteDb/LiteDbConstants.cs
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+namespace Microsoft.SemanticKernel.Connectors.LiteDb;
+
+internal static class LiteDbConstants
+{
+ internal const string VectorStoreSystemName = "LiteDB";
+ internal const string DefaultConnectionString = "Filename=LiteDbVectorStore.db;Connection=shared";
+ internal const string DefaultKeyField = "_id";
+}
diff --git a/dotnet/src/VectorData/LiteDb/LiteDbDynamicCollection.cs b/dotnet/src/VectorData/LiteDb/LiteDbDynamicCollection.cs
new file mode 100644
index 000000000000..6c72db6a9c05
--- /dev/null
+++ b/dotnet/src/VectorData/LiteDb/LiteDbDynamicCollection.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using LiteDB;
+
+namespace Microsoft.SemanticKernel.Connectors.LiteDb;
+
+#pragma warning disable CA1711
+///
+/// Represents a LiteDB collection mapped to dynamic records.
+///
+public sealed class LiteDbDynamicCollection : LiteDbCollection