### Quick Start: Initialize Store, Register Indexes, and Use Session Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/README.md This snippet demonstrates the basic setup for YesSql. It shows how to create and initialize a store using SQLite, register custom indexes, and perform basic save, query, and commit operations within a session. ```csharp // 1. Create and initialize store var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=mydb.sqlite"); }); // 2. Register indexes store.RegisterIndexes(new[] { new UserByNameProvider() }); // 3. Use in sessions using var session = store.CreateSession(); { // Save var user = new User { Name = "Alice" }; await session.SaveAsync(user); // Query var users = await session.Query().ListAsync(); // Commit await session.SaveChangesAsync(); } ``` -------------------------------- ### Complete YesSql Configuration Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/configuration.md Demonstrates a comprehensive configuration setup for YesSql, including database provider, schema, ID generation, concurrency control, command batching, logging, and feature flags. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { // Database provider config.UseSqLite("Data Source=myapp.sqlite", IsolationLevel.ReadCommitted); // Schema config.SetTablePrefix("app_"); config.Schema = null; // Default schema // Columns config.SetIdentityColumnSize(IdentityColumnSize.Int32); // ID generation config.UseBlockIdGenerator(blockSize: 50); // Concurrency config.CheckConcurrentUpdates(); config.CheckConcurrentUpdates(); config.EnableThreadSafetyChecks = false; // Commands config.SetCommandsPageSize(1000); // Logging var logger = LoggerFactory.Create(b => b.AddConsole()) .CreateLogger("YesSql"); config.UseLogger(logger); // Features config.DisableQueryGating(); }); store.RegisterIndexes(new[] { new UserIndexProvider(), new OrderIndexProvider() }); ``` -------------------------------- ### Complete Index Example: BlogPost Indexes Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/indexes.md A comprehensive example demonstrating the definition of map and reduce indexes for BlogPost, including index classes, the provider, registration, and querying. ```csharp // 1. Define index classes public class BlogPostByAuthor : MapIndex { public string Author { get; set; } public DateTime PublishedDate { get; set; } } public class BlogPostCountByStatus : ReduceIndex { public string Status { get; set; } public int Count { get; set; } } // 2. Define index provider public class BlogPostIndexProvider : IndexProvider { public override void Describe(IDescriptor context) { // Map index context .MapIndex() .Map(post => new BlogPostByAuthor { Author = post.Author, PublishedDate = post.PublishedDate }) .When(post => post.Published) .Index(x => x.Author); // Reduce index context .ReduceIndex() .Map(post => new BlogPostCountByStatus { Status = post.Status, Count = 1 }) .Group(x => x.Status) .Reduce(group => new BlogPostCountByStatus { Status = group.Key, Count = group.Sum(x => x.Count) }); } } // 3. Register and use store.RegisterIndexes(new[] { new BlogPostIndexProvider() }); using var session = store.CreateSession(); // Query by map index var alicePosts = await session .Query(x => x.Author == "Alice") .ListAsync(); // Query by reduce index var counts = await session.QueryIndex().ListAsync(); foreach (var c in counts) { Console.WriteLine($"{c.Status}: {c.Count}"); } ``` -------------------------------- ### Example: UserIndexProvider Implementation Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/indexes.md An example of a concrete IndexProvider for the User document type. It defines two map indexes: UserByName and UserByEmail. ```csharp public class UserIndexProvider : IndexProvider { public override void Describe(IDescriptor context) { context .MapIndex() .Map(user => new UserByName { Name = user.Name }) .Index(x => x.Name); context .MapIndex() .Map(user => new UserByEmail { Email = user.Email }) .Index(x => x.Email); } } ``` -------------------------------- ### InitializeAsync Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Initializes the database by creating required tables for documents and the default collection. Must be called before using the store. ```csharp var store = StoreFactory.Create(config); await store.InitializeAsync(); ``` -------------------------------- ### Configuration Property Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Gets the IConfiguration instance used to create this store. ```APIDOC ## Configuration ### Description Gets the `IConfiguration` instance used to create this store. ### Property `IConfiguration Configuration { get; }` ### Example ```csharp var prefix = store.Configuration.TablePrefix; var dialect = store.Configuration.SqlDialect; ``` ``` -------------------------------- ### PropertyAccessorFactory Usage Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md Demonstrates creating and using a property accessor for a 'Id' property. This allows getting and setting property values dynamically. ```csharp // Creates accessor for "Id" property var idFactory = new PropertyAccessorFactory("Id"); var accessor = idFactory.CreateAccessor(typeof(User), "Id"); var user = new User { Id = 123 }; var id = accessor.Get(user); // 123 accessor.Set(user, 456); // user.Id is now 456 ``` -------------------------------- ### UserByName MapIndex Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/indexes.md An example of a concrete MapIndex implementation for storing user names and emails. This is used in conjunction with an IndexProvider to define how User documents are indexed. ```csharp public class UserByName : MapIndex { public string Name { get; set; } public string Email { get; set; } } public class UserByNameProvider : IndexProvider { public override void Describe(IDescribeFor describe) { describe .Map(user => new UserByName { Name = user.Name, Email = user.Email }) .Index(x => x.Name); } } ``` -------------------------------- ### CreateSession Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Creates a new session for database operations. Use withTracking=true to enable change tracking for object state. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config); using var session = store.CreateSession(); var user = await session.Query().FirstOrDefaultAsync(); ``` -------------------------------- ### UserCountByStatus ReduceIndex Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/indexes.md An example of a concrete ReduceIndex implementation to count users by their status. This demonstrates mapping, grouping by status, and reducing to sum the counts. ```csharp public class UserCountByStatus : ReduceIndex { public string Status { get; set; } public int Count { get; set; } } public class UserCountByStatusProvider : IndexProvider { public override void Describe(IDescribeFor describe) { describe .Map(user => new UserCountByStatus { Status = user.Status, Count = 1 }) .Group(x => x.Status) .Reduce(group => new UserCountByStatus { Status = group.Key, Count = group.Sum(x => x.Count) }); } } ``` -------------------------------- ### ISqlDialect Usage Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md Demonstrates how to obtain and use an ISqlDialect instance to generate database-specific SQL types and quoted table names. ```csharp // Usage internally - not typically called by application code var dialect = config.SqlDialect; // SqliteDialect, SqlServerDialect, etc. var sqlType = dialect.GetTypeName(DbType.String, length: 100, precision: null, scale: null); // SQLite: "TEXT" // SQL Server: "varchar(100)" var tableName = dialect.QuoteForTableName("Users", null); // SQLite: "[Users]" // PostgreSQL: "\"Users\"" ``` -------------------------------- ### Document Version Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Shows how the Version property is updated after saving a document and how checkConcurrency can be used to prevent conflicts. ```csharp var user = new User { Name = "Alice" }; await session.SaveAsync(user); // After save, user.Version == 1 user.Name = "Alicia"; await session.SaveAsync(user, checkConcurrency: true); // After save, user.Version == 2 // If another session modified it, checkConcurrency would throw ``` -------------------------------- ### IStringBuilder Usage Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md Demonstrates how to use the IStringBuilder to construct a SQL query with parameters. Ensure you have a dialect's builder instance. ```csharp var builder = dialect.CreateBuilder("app_"); builder.Select(sb => { sb.Append("[Id], "); sb.Append("[Name], "); sb.AppendParameter("status", "active"); }); ``` -------------------------------- ### MapFor Fluent API Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/indexes.md An example demonstrating the use of the MapFor fluent API to define a mapping function from a User document to a UserByName index, including an optional filter predicate. ```csharp describe .Map(user => new UserByName { Name = user.Name }) .When(user => !user.IsDeleted); ``` -------------------------------- ### Define a Map Index for Blog Posts by Author Source: https://github.com/sebastienros/yessql/wiki/Tutorial Implement IIndexProvider to register a map index. This example shows how to index BlogPosts by their Author property. ```csharp public class BlogPostIndexProvider : IndexProvider { public override void Describe(DescribeContext context) { // for each BlogPost, create a BlogPostByAuthor index context.For().Map(blogPost => new BlogPostByAuthor { Author = blogPost.Author }); } } ``` -------------------------------- ### Document Type Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Demonstrates how to retrieve and display the Type property of a document, showing the difference with and without the SimplifiedTypeNameAttribute. ```csharp // Without attribute var doc = await session.Query().Any().FirstOrDefaultAsync(); Console.WriteLine(doc.Type); // "MyNamespace.Models.User" // With attribute [SimplifiedTypeName("User")] public class User { } // Type is now just "User" ``` -------------------------------- ### SchemaBuilder Usage Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md Example of using SchemaBuilder to create a 'User' table with an integer primary key 'Id' and a string 'Name' column. Requires an active transaction. ```csharp var builder = new SchemaBuilder(store.Configuration, transaction); await builder.CreateTableAsync("User", table => table .Column("Id", col => col.PrimaryKey()) .Column("Name") ); ``` -------------------------------- ### ISqlBuilder Usage Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md Demonstrates building a simple SQL SELECT query using the ISqlBuilder interface, including specifying table prefix and WHERE clause. ```csharp var builder = dialect.CreateBuilder("app_"); builder.Select(s => s.Append("[Id], [Name]")); builder.From(f => f.Append("[User]")); builder.Where(w => w.Append("[Status] = @p0")); var sql = builder.ToSql(out var parameters); // SELECT [Id], [Name] FROM [app_User] WHERE [Status] = @p0 ``` -------------------------------- ### InitializeCollectionAsync Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Initializes a specific named collection by creating its required tables. Collections partition documents into separate logical groups. ```csharp await store.InitializeCollectionAsync("customers"); await store.InitializeCollectionAsync("orders"); ``` -------------------------------- ### Describe Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Returns index descriptors for all indexes associated with a document type in a collection. Useful for inspecting index configurations. ```csharp var descriptors = store.Describe(typeof(BlogPost)); foreach (var desc in descriptors) { Console.WriteLine($"Index: {desc.Type.Name}"); } ``` -------------------------------- ### Document Clone Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Demonstrates the usage of the Clone method, showing that the Content property of the copied document can be modified independently of the original. ```csharp var original = new Document { Id = 1, Type = "User", Content = "{...}", Version = 1 }; var copy = original.Clone(); copy.Content = "{modified}"; Console.WriteLine(original.Content); // "{...}" (unchanged) Console.WriteLine(copy.Content); // "{modified}" ``` -------------------------------- ### RegisterIndexes Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Registers index providers globally to the store for all documents of their target type. Ensure index provider classes are defined. ```csharp store.RegisterIndexes(new[] { new BlogPostByAuthorProvider(), new BlogPostByDayProvider() }); ``` -------------------------------- ### Get All Matching Documents Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/query.md Returns all documents matching the constraints. This is the default execution method for retrieving multiple results. ```csharp var users = await session.Query() .ListAsync(); ``` -------------------------------- ### Example: Reduce Index for User Count by Status Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/indexes.md Demonstrates how to define a reduce index that groups users by status and sums their counts. This is useful for aggregating data based on a specific property. ```csharp describe .Map(user => new UserCountByStatus { Status = user.Status, Count = 1 }) .Group(x => x.Status) .Reduce(group => new UserCountByStatus { Status = group.Key, Count = group.Sum(x => x.Count) }); ``` -------------------------------- ### Define a Map/Reduce Index for Blog Posts by Day Source: https://github.com/sebastienros/yessql/wiki/Tutorial Create a ReduceIndex to aggregate data. This example computes the count of blog posts published per day. ```csharp public class BlogPostByDay : ReduceIndex { public virtual string Day { get; set; } public virtual int Count { get; set; } } ``` -------------------------------- ### Implement SimpleFilterParser Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/filters.md An example implementation of IFilterParser that parses filter text into a FilterNode tree. This demonstrates how to create a concrete parser. ```csharp public class SimpleFilterParser : IFilterParser { public FilterNode Parse(string text) { // Parse "Name:Alice AND Status:Active" into FilterNode tree // Implementation details... return new FilterNode { /* ... */ }; } } ``` -------------------------------- ### Describe Map/Reduce Index Logic Source: https://github.com/sebastienros/yessql/wiki/Tutorial Describe the map, group, reduce, and delete functions for a map/reduce index. This example aggregates blog posts by publication day. ```csharp // for each BlogPost, aggregate in an exiting BlogPostByDay context.For() .Map( blogPost => new BlogPostByDay { Day = blogPost.PublishedUtc.ToString("yyyyMMdd"), Count = 1 }) .Group( blogPost => blogPost.Day ) .Reduce( group => new BlogPostByDay { Day = group.Key, Count = group.Sum(p => p.Count) }) .Delete( (index, map) => { index.Count -= map.Sum(x => x.Count); // if Count == 0 then delete the index return index.Count > 0 ? index : null; }); ``` -------------------------------- ### Configure Block ID Generator Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md Example of configuring the block ID generator with a specified block size. This is done during the YesSql configuration. ```csharp config.UseBlockIdGenerator(blockSize: 100); ``` -------------------------------- ### Document Content Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Illustrates how YesSql internally creates a Document object with its Content property populated from a C# object during saving. ```csharp // When saving this: var user = new User { Id = 1, Name = "Alice", Email = "alice@example.com" }; await session.SaveAsync(user); // YesSql internally creates: var doc = new Document { Id = 1, Type = "User", Content = "{\"id\":1,\"name\":\"Alice\",\"email\":\"alice@example.com\",\"version\":1}", Version = 1 }; ``` -------------------------------- ### Get First or Default Document Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/query.md Returns the first result matching the constraints, or null if no matching document is found. Use this when you expect at most one result. ```csharp var user = await session.Query() .FirstOrDefaultAsync(); ``` -------------------------------- ### Example: Custom Delete Logic for Index Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/indexes.md Shows how to implement custom logic for deleting index records. The provided lambda function receives the deleted index and remaining indexes to compute the new state. ```csharp describe .Map(...) .Group(...) .Reduce(...) .Delete((deletedIndex, remainingIndexes) => { // Custom delete logic return new UserCountByStatus { Status = deletedIndex.Status, Count = remainingIndexes.Sum(x => x.Count) }; }); ``` -------------------------------- ### Implement FilterToWhereClauseVisitor Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/filters.md An example implementation of IFilterVisitor that converts filter nodes into a SQL WHERE clause string. This demonstrates processing different node types. ```csharp public class FilterToWhereClausVisitor : IFilterVisitor { public string Visit(TermNode node, object argument) { // Convert term like "Status:Active" to SQL return $ ``` ```csharp [{node.Field}] = '{node.Value}'"; } public string Visit(AndTermNode node, object argument) { var left = node.Left.Accept(this, argument); var right = node.Right.Accept(this, argument); return $"({left} AND {right})"; } public string Visit(OrNode node, object argument) { var left = node.Left.Accept(this, argument); var right = node.Right.Accept(this, argument); return $"({left} OR {right})"; } // ... implement other Visit methods } ``` -------------------------------- ### Describe Document Indexes Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/types.md Retrieves and prints the CLR type name and database table name for indexes associated with a specific document type. ```csharp var descriptors = store.Describe(typeof(User)); foreach (var desc in descriptors) { Console.WriteLine($"{desc.Type.Name}: {desc.TableName}"); } ``` -------------------------------- ### BlogPost Mapped Index Example Source: https://github.com/sebastienros/yessql/wiki/Tutorial Defines a mapped index for the BlogPost class, specifically for the Author property. This class inherits from MapIndex and is used for elementary queries on document properties. ```csharp public class BlogPostByAuthor : MapIndex { ``` -------------------------------- ### Store Property Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/session.md Gets the IStore instance that created this session. This property provides access to the underlying store configuration and management capabilities. ```APIDOC ## Store ### Description Gets the `IStore` instance that created this session. ### Method `ISession.Store` ### Endpoint N/A (Property Access) ### Parameters - None ### Returns - **Type**: `IStore` - **Description**: The `IStore` instance that created this session. ``` -------------------------------- ### Retrieve Type Metadata Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Shows how to get metadata about a document type, including available indexes and table names, using the store's `Describe` method. ```csharp // Get type information var descriptors = store.Describe(typeof(User)); // Check what indexes are available foreach (var desc in descriptors) { Console.WriteLine($"Index: {desc.Type.Name}"); Console.WriteLine($"Table: {desc.TableName}"); } ``` -------------------------------- ### Recommended Usage: Create and Initialize with Delegate Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Demonstrates the recommended pattern for creating and initializing an IStore using a configuration delegate, followed by registering indexes. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=mydb.sqlite"); config.SetTablePrefix("myapp"); }); store.RegisterIndexes(new[] { new UserByNameProvider() }); ``` -------------------------------- ### IdAccessor Implementation Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/types.md Implements IAccessor to specifically get and set the 'Id' property on objects that implement IDocument. ```csharp public class IdAccessor : IAccessor { public long Get(object obj) { if (obj is IDocument doc) return doc.Id; return 0; } public void Set(object obj, long value) { if (obj is IDocument doc) doc.Id = value; } } ``` -------------------------------- ### C# Filter Validation Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/filters.md Shows how to use a parser and a validation visitor to check if a user-provided filter expression is valid against a set of allowed fields. This is crucial for security and preventing invalid queries. ```csharp var filterNode = parser.Parse(userInput); var valid = filterNode.Accept(validationVisitor, allowedFields); ``` -------------------------------- ### Configure Query Filter for BlogPost Source: https://github.com/sebastienros/yessql/wiki/Query-Filters Configures an IQueryParser for BlogPost documents, registering a named 'sort' term with a OneCondition and a default 'title' term with a ManyCondition. This setup allows for sorting by publication date and filtering titles using boolean logic. ```csharp services.AddSingleton>(sp => new QueryEngineBuilder() .WithNamedTerm("sort", b => b .OneCondition((val, query) => { if (Enum.TryParse(val, true, out var e)) { switch (e) { case BlogPostSort.Newest: query.With().OrderByDescending(x => x.PublishedUtc); break; case BlogPostSort.Oldest: query.With().OrderBy(x => x.PublishedUtc); break; default: query.With().OrderByDescending(x => x.PublishedUtc); break; } } else { query.With().OrderByDescending(x => x.PublishedUtc); } return query; }) .AlwaysRun() ) .WithDefaultTerm("title", b => b .ManyCondition( ((val, query) => query.With(x => x.Title.Contains(val))), ((val, query) => query.With(x => x.Title.IsNotIn(s => s.Title, w => w.Title.Contains(val)))) ) ) .Build() ); ``` -------------------------------- ### Custom SQLite Connection Factory Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md An example implementation of IConnectionFactory for SQLite. It provides a way to create new SQLite database connections using a given connection string. ```csharp public class SqliteConnectionFactory : IConnectionFactory { private readonly string _connectionString; public SqliteConnectionFactory(string connectionString) { _connectionString = connectionString; } public DbConnection CreateConnection() { return new SqliteConnection(_connectionString); } public Type DbConnectionType => typeof(SqliteConnection); } ``` -------------------------------- ### Complete Store Initialization and Configuration Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Demonstrates the complete process of creating and initializing a YesSql store using StoreFactory.ConfigureAsync. This includes setting up the database connection, table prefix, identity column size, concurrent update checks, block ID generator, and disabling query gating. It also shows how to register global indexes and perform a basic query. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=mydb.sqlite"); config.SetTablePrefix("myapp_"); config.SetIdentityColumnSize(IdentityColumnSize.Int64); config.CheckConcurrentUpdates(); config.UseBlockIdGenerator(blockSize: 20); config.DisableQueryGating(); }); // Register global indexes store.RegisterIndexes(new[] { new UserByNameProvider(), new UserByEmailProvider() }); // Create a session and use it using var session = store.CreateSession(); var users = await session.Query().ListAsync(); ``` -------------------------------- ### Count Blog Posts by Day using Map/Reduce Index Source: https://github.com/sebastienros/yessql/wiki/Tutorial Query the BlogPostByDay map/reduce index directly to get aggregated counts per day. This does not retrieve the full BlogPost documents. ```csharp // counting blog posts by day await using (var session = store.CreateSession()) { var days = await session.QueryIndex().ListAsync(); foreach (var day in days) { Console.WriteLine(day.Day + ": " + day.Count); // > [Today]: 1 } } ``` -------------------------------- ### Initialize Store and Collections Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Demonstrates initializing the YesSql store with a specific configuration and setting up collections. Indexes can also be registered for these collections. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=mydb.sqlite"); }); await store.InitializeCollectionAsync("customers"); await store.InitializeCollectionAsync("orders"); store.RegisterIndexes(new[] { new CustomerIndexProvider { CollectionName = "customers" }, new OrderIndexProvider { CollectionName = "orders" } }); ``` -------------------------------- ### C# Filter Parsing Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/filters.md Demonstrates parsing a user-friendly filter expression like "Author:Alice AND Status:Published" into a filter tree. This is useful for converting string inputs into a structured format for further processing. ```csharp // User enters: "Author:Alice AND Status:Published" // System parses and executes SQL query ``` -------------------------------- ### Usage: Create and Initialize with Configuration Object Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Shows how to create and initialize an IStore using a pre-configured Configuration object. ```csharp var config = new Configuration(); config.UseSqLite("Data Source=mydb.sqlite"); config.SetTablePrefix("myapp"); var store = await StoreFactory.CreateAndInitializeAsync(config); ``` -------------------------------- ### Create and Initialize IStore with Configuration Delegate Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates and immediately initializes an IStore instance using a configuration delegate. The store is ready for use upon return. ```csharp public static async Task CreateAndInitializeAsync(Action configuration) ``` ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=:memory:"); }); // Store is ready to use var session = store.CreateSession(); ``` -------------------------------- ### Usage: Manual Creation and Initialization Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Illustrates the pattern for manually creating an IStore instance using a configuration delegate and then explicitly initializing it. ```csharp var store = StoreFactory.Create(config => { config.UseSqLite("Data Source=mydb.sqlite"); }); // Perform setup tasks... await store.InitializeAsync(); ``` -------------------------------- ### Collection Initialization Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Illustrates how to initialize collections, including the default collection which happens automatically, and named collections explicitly. ```csharp // Initialize default collection (happens automatically) await store.InitializeAsync(); // Initialize named collections await store.InitializeCollectionAsync("customers"); await store.InitializeCollectionAsync("orders"); ``` -------------------------------- ### TypeNames Property Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Gets the ITypeService instance used to manage type name mappings. ```APIDOC ## TypeNames ### Description Gets the `ITypeService` instance used to manage type name mappings. ### Property `ITypeService TypeNames { get; }` ### Example ```csharp var typeName = store.TypeNames.GetTypeName(typeof(User)); ``` ``` -------------------------------- ### StoreFactory.CreateAndInitializeAsync (with configuration delegate) Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates and immediately initializes an IStore instance using a configuration delegate. The returned store is ready for use. ```APIDOC ## StoreFactory.CreateAndInitializeAsync (with configuration delegate) ### Description Creates and immediately initializes an `IStore` instance using a configuration delegate. ### Method ```csharp public static async Task CreateAndInitializeAsync(Action configuration) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **configuration** (`Action`) - Required - Action to configure the store. ### Returns `Task` — An initialized and ready-to-use store instance. ### Example ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=:memory:"); }); // Store is ready to use var session = store.CreateSession(); ``` ``` -------------------------------- ### Create, Initialize, Register Indexes, and Query Store Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md This snippet demonstrates the complete typical workflow for using the Yessql store. It shows how to create and initialize the store with a SQLite in-memory database, register a custom index, create a session, and query for users. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=:memory:"); }); store.RegisterIndexes(new[] { new UserByNameProvider() }); using var session = store.CreateSession(); var users = await session.Query().ListAsync(); ``` -------------------------------- ### IAccessor Interface Definition Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/types.md Provides a generic mechanism for getting and setting property values on objects. ```csharp public interface IAccessor { T Get(object obj); void Set(object obj, T value); } ``` -------------------------------- ### IAccessor Interface Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/types.md Provides generic access to property values on objects, with methods to get and set values. ```APIDOC ## IAccessor Interface ### Description Provides generic access to property values on objects. ### Methods - **Get(object obj)** (T) - Reads a value from an object - **Set(object obj, T value)** (void) - Writes a value to an object ### Usage Example ```csharp public class IdAccessor : IAccessor { public long Get(object obj) { if (obj is IDocument doc) return doc.Id; return 0; } public void Set(object obj, long value) { if (obj is IDocument doc) doc.Id = value; } } ``` ``` -------------------------------- ### StoreFactory.CreateAndInitializeAsync (with IConfiguration) Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates and immediately initializes an IStore instance using an existing IConfiguration object. The returned store is ready for use. ```APIDOC ## StoreFactory.CreateAndInitializeAsync (with IConfiguration) ### Description Creates and immediately initializes an `IStore` instance using an existing `IConfiguration` object. ### Method ```csharp public static async Task CreateAndInitializeAsync(IConfiguration configuration) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **configuration** (`IConfiguration`) - Required - An already-configured `IConfiguration` instance. ### Returns `Task` — An initialized and ready-to-use store instance. ### Example ```csharp var config = new Configuration(); config.UseSqLite("Data Source=mydb.sqlite"); var store = await StoreFactory.CreateAndInitializeAsync(config); // Store is ready to use ``` ``` -------------------------------- ### Create and Initialize Store Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/README.md Create and initialize the YesSql store with a specific database provider and optional table prefix. This is the entry point for using YesSql. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config => { config.UseSqLite("Data Source=mydb.sqlite"); config.SetTablePrefix("app_"); }); ``` -------------------------------- ### Create and Initialize IStore with Existing IConfiguration Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates and immediately initializes an IStore instance using a pre-configured IConfiguration object. The store is ready for use upon return. ```csharp public static async Task CreateAndInitializeAsync(IConfiguration configuration) ``` ```csharp var config = new Configuration(); config.UseSqLite("Data Source=mydb.sqlite"); var store = await StoreFactory.CreateAndInitializeAsync(config); // Store is ready to use ``` -------------------------------- ### DefaultTableNameConvention Usage Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md Demonstrates how DefaultTableNameConvention converts CLR types to table names. The convention is used automatically by YesSql. ```csharp var convention = new DefaultTableNameConvention(); convention.GetTableName(typeof(User)); // "User" convention.GetTableName(typeof(BlogPost)); // "BlogPost" ``` -------------------------------- ### SimplifiedTypeNameAttribute Usage Example Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/types.md Applies a custom simplified name 'User' to a document class, which will be used instead of its fully-qualified name in the database. ```csharp [SimplifiedTypeName("User")] public class MyApp.Domain.User { public string Name { get; set; } } ``` -------------------------------- ### Create IStore with Configuration Delegate Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates an IStore instance using a configuration delegate. The returned store requires manual initialization via InitializeAsync(). ```csharp public static IStore Create(Action configuration) ``` ```csharp var store = StoreFactory.Create(config => { config.UseSqLite("Data Source=mydb.sqlite"); config.SetTablePrefix("app"); }); await store.InitializeAsync(); ``` -------------------------------- ### InitializeAsync Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Initializes the database by creating required tables for documents and the default collection. This must be called before using the store. ```APIDOC ## InitializeAsync ### Description Initializes the database by creating required tables for documents and the default collection. This must be called before using the store. ### Method `Task InitializeAsync(CancellationToken cancellationToken = default)` ### Parameters #### Path Parameters * **cancellationToken** (CancellationToken) - Optional - Token to cancel the operation ### Returns `Task` — Completes when initialization is done. ### Remarks Creates the global `Document` table and any index tables. ### Example ```csharp var store = StoreFactory.Create(config); await store.InitializeAsync(); ``` ``` -------------------------------- ### StoreFactory.Create (with IConfiguration) Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates an IStore instance using an existing IConfiguration object. The returned store requires a subsequent call to InitializeAsync(). ```APIDOC ## StoreFactory.Create (with IConfiguration) ### Description Creates an `IStore` instance using an existing `IConfiguration` object. ### Method ```csharp public static IStore Create(IConfiguration configuration) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **configuration** (`IConfiguration`) - Required - An already-configured `IConfiguration` instance. ### Returns `IStore` — A new store instance. ### Remarks The returned store must still be initialized with `InitializeAsync()`. ### Example ```csharp var config = new Configuration(); config.UseSqLite("Data Source=mydb.sqlite"); var store = StoreFactory.Create(config); await store.InitializeAsync(); ``` ``` -------------------------------- ### Custom ID Generator Implementation Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md An example of a custom IIdGenerator that generates sequential IDs. It uses Interlocked.Increment for thread-safe ID generation. ```csharp public class CustomIdGenerator : IIdGenerator { private long _nextId = 1; public Task InitializeAsync(IStore store, CancellationToken cancellationToken = default) { return Task.CompletedTask; } public Task InitializeCollectionAsync( IConfiguration configuration, string collection, CancellationToken cancellationToken = default) { return Task.CompletedTask; } public Task GetNextIdAsync(string collection, CancellationToken cancellationToken = default) { // Thread-safe increment return Task.FromResult(Interlocked.Increment(ref _nextId)); } } ``` -------------------------------- ### Custom MessagePack Content Serializer Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/miscellaneous.md An example implementation of IContentSerializer using MessagePack for serialization. This can be configured to replace the default JSON serializer. ```csharp public class MessagePackSerializer : IContentSerializer { public string Serialize(object item) { var bytes = MessagePackSerializer.Serialize(item); return Convert.ToBase64String(bytes); } public object Deserialize(string content, Type type) { var bytes = Convert.FromBase64String(content); return MessagePackSerializer.Deserialize(type, bytes); } } // Configure config.SetContentSerializer(new MessagePackSerializer()); ``` -------------------------------- ### Create and Save New Document Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Demonstrates the process of creating a new document object, saving it to the session, and then committing the changes to the database. ```csharp // Create new document (no ID yet) var user = new User { Name = "Alice" }; using var session = store.CreateSession(); { // Save to session (queued, not committed) await session.SaveAsync(user); // At this point, user has been assigned an ID by the ID generator var assignedId = user.Id; // Commit to database await session.SaveChangesAsync(); } ``` -------------------------------- ### Create IStore with Existing IConfiguration Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates an IStore instance using a pre-configured IConfiguration object. The returned store requires manual initialization via InitializeAsync(). ```csharp public static IStore Create(IConfiguration configuration) ``` ```csharp var config = new Configuration(); config.UseSqLite("Data Source=mydb.sqlite"); var store = StoreFactory.Create(config); await store.InitializeAsync(); ``` -------------------------------- ### Read Documents by Query Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Illustrates how to fetch multiple documents that match certain criteria using a query. ```csharp // By Query using var session = store.CreateSession(); { var users = await session.Query().ListAsync(); } ``` -------------------------------- ### Initialize and Use Collections Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/README.md Organize documents into named collections. Initialize a collection before use and specify the collection name when saving or querying documents. ```csharp // Initialize collection await store.InitializeCollectionAsync("customers"); // Save to collection await session.SaveAsync(customer, collection: "customers"); // Query from collection var customers = await session.Query(collection: "customers") .ListAsync(); ``` -------------------------------- ### CountAsync Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/query.md Returns the number of documents matching the query constraints. This method is efficient for getting a count without retrieving the actual documents. ```APIDOC ## CountAsync ### Description Returns the number of documents matching the constraints. ### Method `Task CountAsync(CancellationToken cancellationToken = default)` ### Returns `Task` — Count of matching documents. ### Example ```csharp int count = await session.Query().CountAsync(); ``` ``` -------------------------------- ### Get SQL Alias with GetTypeAlias Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/query.md GetTypeAlias retrieves the SQL alias assigned to a specific type within the context of the current query. ```csharp string GetTypeAlias(Type t) ``` -------------------------------- ### StoreFactory.Create (with configuration delegate) Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store-factory.md Creates an IStore instance using a configuration delegate. The returned store requires a subsequent call to InitializeAsync(). ```APIDOC ## StoreFactory.Create (with configuration delegate) ### Description Creates an `IStore` instance with a new configuration provided via a delegate. ### Method ```csharp public static IStore Create(Action configuration) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **configuration** (`Action`) - Required - Action to configure the store. ### Returns `IStore` — A new unconfigured store instance. ### Remarks The returned store must be initialized by calling `InitializeAsync()` before use. ### Example ```csharp var store = StoreFactory.Create(config => { config.UseSqLite("Data Source=mydb.sqlite"); config.SetTablePrefix("app"); }); await store.InitializeAsync(); ``` ``` -------------------------------- ### Common Session Usage Pattern Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/session.md Demonstrates a typical workflow for using an ISession, including creating a store, managing sessions, saving, querying, updating, and deleting documents, followed by committing changes. ```csharp var store = await StoreFactory.CreateAndInitializeAsync(config); // Create a session using var session = store.CreateSession(); // Save a document var user = new User { Name = "Alice" }; await session.SaveAsync(user); await session.SaveChangesAsync(); // Query documents var users = await session.Query().ListAsync(); // Update user.Name = "Alicia"; await session.SaveAsync(user); await session.SaveChangesAsync(); // Delete session.Delete(user); await session.SaveChangesAsync(); ``` -------------------------------- ### Using Default Collection Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Demonstrates how to save a document using the default collection, either implicitly or by explicitly specifying null for the collection parameter. ```csharp // Uses default collection await session.SaveAsync(user); // Explicitly use default collection (null) await session.SaveAsync(user, collection: null); ``` -------------------------------- ### Load a BlogPost Document Source: https://github.com/sebastienros/yessql/wiki/Tutorial Loads the first BlogPost document found in the store using a query. The title of the loaded post is then printed to the console. ```csharp // loading an single blog post await using(var session = store.CreateSession()) { var p = await session.Query().FirstOrDefaultAsync(); Console.WriteLine(p.Title); // > Hello YesSql } ``` -------------------------------- ### Configure and Initialize YesSql Store Source: https://github.com/sebastienros/yessql/wiki/Tutorial Initializes a YesSql store instance using SQLite and sets a table prefix. This is typically done once per application as a singleton. ```csharp var store = await StoreFactory.CreateAndInitializeAsync( new Configuration() .UseSqLite(@"Data Source=yessql.db;Cache=Shared") .SetTablePrefix("Hi") ); ``` -------------------------------- ### Session Extension Methods Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/README.md Use session extension methods for common operations like getting documents by ID, registering indexes, importing items, or detaching from the cache. ```csharp // SessionExtensions session.GetAsync(id) // Get by ID (returns one) session.RegisterIndexes(indexProviders) // Register for session session.Import(item, id, version) // Import to identity map session.Detach(item) // Remove from cache ``` -------------------------------- ### Define Index Provider for a Collection Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Illustrates how to create a custom index provider for a specific document type and how to register it for a designated collection. ```csharp public class CustomerIndexProvider : IndexProvider { public override void Describe(IDescriptor context) { context .MapIndex() .Map(c => new CustomerByName { Name = c.Name }) .Index(x => x.Name); } } // When registering, specify the collection var provider = new CustomerIndexProvider { CollectionName = "customers" }; store.RegisterIndexes(new[] { provider }); ``` -------------------------------- ### Accessing Store Configuration Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/store.md Retrieves the IConfiguration instance used to create the store. Access properties like TablePrefix and SqlDialect. ```csharp var prefix = store.Configuration.TablePrefix; var dialect = store.Configuration.SqlDialect; ``` -------------------------------- ### Create a Basic Query Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/session.md Creates a query builder for a specific collection. This query can then be chained with methods like For() and ListAsync() to retrieve documents. ```csharp var query = session.Query(); var users = await query.For().ListAsync(); ``` -------------------------------- ### AlwaysRun Default Sort Source: https://github.com/sebastienros/yessql/wiki/Query-Filters Ensures a condition's MatchQuery always runs, even if the term is not specified, to provide a default value. This example applies a default sort expression if no valid sort is provided. ```csharp if (Enum.TryParse(val, true, out var e)) { ... } else { // Apply a default sort expression. query.OrderByDescending(x => x.PublishedUtc); } ``` -------------------------------- ### Configure Serialization and Logging Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/README.md Configure custom serializers for document content or integrate a custom logger with YesSql. This allows for flexible data handling and monitoring. ```csharp config.SetContentSerializer(customSerializer); config.UseLogger(logger); ``` -------------------------------- ### ITableNameConvention Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/types.md Defines the convention for converting CLR type names into database table names. It provides methods to get the table name and an optional prefix for a given type, allowing for flexible table naming strategies. ```APIDOC ## Interface ITableNameConvention ### Description Defines how CLR type names are converted to database table names. ### Methods #### GetTableName(Type type) - **Description**: Gets the table name for a type. - **Returns**: string #### GetTablePrefix(Type type) - **Description**: Gets the prefix for a type. - **Returns**: string ### Source `src/YesSql.Abstractions/ITableNameConvention.cs` ``` -------------------------------- ### Proper Session Management in YesSql Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Illustrates the correct way to manage YesSql sessions using `using` statements for automatic disposal. Avoid leaving sessions open without disposal. ```csharp // Good: Dispose sessions using var session = store.CreateSession(); { var user = await session.GetAsync(1); await session.SaveChangesAsync(); } // Avoid: Not disposing var session = store.CreateSession(); var user = await session.GetAsync(1); ``` -------------------------------- ### Create User and UserIndex Tables with Foreign Key Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/schema-builder.md This snippet demonstrates how to use SchemaBuilder to create a 'User' table with primary key, not null, unique, and nullable constraints, an 'UserIndex_ByEmail' table, and a foreign key relationship between them. Ensure you have a store configuration and an open connection with a transaction. ```csharp using var connection = store.Configuration.ConnectionFactory.CreateConnection(); await connection.OpenAsync(); using var transaction = await connection.BeginTransactionAsync( store.Configuration.IsolationLevel); var builder = new SchemaBuilder(store.Configuration, transaction); // Create main table await builder.CreateTableAsync("User", table => table .Column("Id", col => col.PrimaryKey()) .Column("Name", col => col.NotNull().Length(100)) .Column("Email", col => col.NotNull().Unique().Length(100)) .Column("Phone", col => col.Nullable()) .Column("CreatedUtc") .Column("Version") ); // Create index table await builder.CreateTableAsync("UserIndex_ByEmail", table => table .Column("Id", col => col.PrimaryKey()) .Column("Email", col => col.NotNull().Unique().Length(100)) .Column("DocumentId", col => col.NotNull()) ); // Create foreign key await builder.CreateForeignKeyAsync( "FK_UserIndex_Document", "UserIndex_ByEmail", new[] { "DocumentId" }, "Document", new[] { "Id" } ); await transaction.CommitAsync(); ``` -------------------------------- ### Update Document Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Details the steps to retrieve an existing document, modify its properties, and save the changes back to the database. ```csharp using var session = store.CreateSession(); { var user = await session.GetAsync(1); user.Name = "Alicia"; await session.SaveAsync(user); await session.SaveChangesAsync(); } ``` -------------------------------- ### Create Schema Async Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/schema-builder.md Creates a database schema (namespace). Supported by PostgreSQL and SQL Server. Note that SQLite and MySQL use database-level schemas. ```csharp await builder.CreateSchemaAsync("myapp"); ``` -------------------------------- ### Typed vs. Untyped Queries in YesSql Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/api-reference/document.md Demonstrates the recommended approach of using type-safe queries for better maintainability and safety. Avoid untyped queries when possible. ```csharp // Good: Type-safe var user = await session.Query().FirstOrDefaultAsync(); // Avoid: Untyped var doc = await session.Query().Any().FirstOrDefaultAsync(); ``` -------------------------------- ### Configuration Class Definition Source: https://github.com/sebastienros/yessql/blob/main/_autodocs/types.md Defines the default implementation of the IConfiguration interface, specifying various settings for database interaction, serialization, and query execution. Properties include accessor factories, isolation level, content serializer, table prefix, schema, command page size, query gating, thread safety checks, ID generator, logger, concurrent types, table name convention, command interpreter, SQL dialect, and identity column size. ```csharp public class Configuration : IConfiguration { public Configuration() public IAccessorFactory IdentifierAccessorFactory { get; set; } public IAccessorFactory VersionAccessorFactory { get; set; } public IsolationLevel IsolationLevel { get; set; } public IConnectionFactory ConnectionFactory { get; set; } public IContentSerializer ContentSerializer { get; set; } public string TablePrefix { get; set; } public string Schema { get; set; } public int CommandsPageSize { get; set; } public bool QueryGatingEnabled { get; set; } public bool EnableThreadSafetyChecks { get; set; } public IIdGenerator IdGenerator { get; set; } public ILogger Logger { get; set; } public HashSet ConcurrentTypes { get; } public ITableNameConvention TableNameConvention { get; set; } public ICommandInterpreter CommandInterpreter { get; set; } public ISqlDialect SqlDialect { get; set; } public IdentityColumnSize IdentityColumnSize { get; set; } } ```