### Basic Sync Agent Initialization and Synchronization Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Progression.rst Demonstrates the fundamental setup of a SyncAgent with SQL providers and sync setup, followed by initiating a synchronization loop. This example shows the core components needed to start a sync process. ```csharp var serverProvider = new SqlSyncChangeTrackingProvider(serverConnectionString); var clientProvider = new SqlSyncProvider(clientConnectionString); var setup = new SyncSetup("ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" ); var agent = new SyncAgent(clientProvider, serverProvider); do { // Launch the sync process var s1 = await agent.SynchronizeAsync(setup); // Write results Console.WriteLine(s1); } while (Console.ReadKey().Key != ConsoleKey.Escape); Console.WriteLine("End"); ``` -------------------------------- ### Dotmim.Sync CLI: Project Creation and Management Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/CLI.md This snippet demonstrates the basic CLI commands for creating, listing, getting information about, and deleting Dotmim.Sync projects. It requires the Dotmim.Sync CLI to be installed. ```bash $ dotnet sync -n "syncproject01" Project "syncproject01" created ``` ```bash $ dotnet sync -ls PROJECT SERVER PROVIDER CLIENT PROVIDER TABLES p0 SqlServer Sqlite 7 advworkspj SqlServer Sqlite 2 contoso SqlServer Sqlite 2 proxy Web Sqlite - ``` ```bash $ dotnet sync -i "syncproject01" PROJECT syncproject01 SERVER PROVIDER SqlServer SERVER PROVIDER CS data source=(localdb)\mssqllocaldb; initial catalog=adventureworks; integrated security=true; CLIENT PROVIDER Sqlite CLIENT PROVIDER CS c:\users\johndoe\.dmsync\advworks.db CONF CONFLICT ServerWins CONF BATCH DIR C:\Users\johndoe\AppData\Local\Temp\DotmimSync CONF BATCH SIZE 0 CONF SERIALIZATION Json CONF BULK OPERATIONS True TABLE SCHEMA DIRECTION ORDER ProductCategory Bidirectional 0 ProductDescription Bidirectional 1 ProductModel Bidirectional 2 Product Bidirectional 3 Address Bidirectional 4 Customer Bidirectional 5 CustomerAddress Bidirectional 6 ``` ```bash $ dotnet sync project -r "syncproject01" Project "syncproject01" deleted. ``` -------------------------------- ### Initial Synchronization Setup and Execution (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Provision.rst This snippet demonstrates the initial setup for a synchronization process using Dotmim Sync. It configures SQL and SQLite sync providers, defines a sync setup with specified tables, creates sync agents, and initiates the first synchronization using a 'v0' scope. It also shows how to use `SynchronousProgress` to monitor the synchronization progress. ```csharp // Create the server Sync provider var serverProvider = new SqlSyncProvider(serverConnectionString); // Create 2 clients. First will migrate, 2nd will stay without new column var client1Provider = new SqlSyncProvider(clientConnectionString); var databaseName = $"{Path.GetRandomFileName().Replace(".", "").ToLowerInvariant()}.db"; var client2Provider = new SqliteSyncProvider(databaseName); // Create standard Setup var setup = new SyncSetup("Address", "Customer", "CustomerAddress"); // Creating agents that will handle all the process var agent1 = new SyncAgent(client1Provider, serverProvider); var agent2 = new SyncAgent(client2Provider, serverProvider); // Using the Progress pattern to handle progession during the synchronization var progress = new SynchronousProgress( args => Console.WriteLine($"{args.ProgressPercentage:p}:\t{args.Message}")); // First sync to have a starting point // To make a full example, we are going to use differente scope name (v0, v1) // v0 is the initial database // v1 will contains the new column in the Address table var s1 = await agent1.SynchronizeAsync("v0", setup, progress); Console.WriteLine("Initial Sync on Sql Server Client 1"); Console.WriteLine(s1); var s2 = await agent2.SynchronizeAsync("v0", setup, progress); Console.WriteLine("Initial Sync on Sqlite Client 2"); Console.WriteLine(s2); ``` -------------------------------- ### Dotmim.Sync Test Configuration Example Source: https://github.com/mimetis/dotmim.sync/wiki/Unit-tests-project.-How-it-works This C# code snippet illustrates how to configure tests for Dotmim.Sync providers within the Setup class's OnConfiguring method. It shows how to specify tables for SQL Server and MySQL, add database names, and define which provider and network type combinations should be tested, including conditional logic for specific environments like AppVeyor. ```csharp internal static void OnConfiguring(ProviderFixture providerFixture) where T : CoreProvider { // Set tables to be used for SQL Server (including schema) var sqlTables = new string[] { "SalesLT.ProductCategory", "SalesLT.ProductModel", "SalesLT.Product", "Customer", "Address", "CustomerAddress", "SalesLT.SalesOrderHeader", "SalesLT.SalesOrderDetail", "dbo.Sql", "Posts", "Tags", "PostTag" }; // Set tables to be used for MySql var mySqlTables = new string[] { "productcategory", "productmodel", "product", "customer", "address","customeraddress", "salesorderheader", "salesorderdetail", "sql", "posts", "tags", "posttag" }; // 1) Add database name providerFixture.AddDatabaseName(ProviderType.Sql, "SqlAdventureWorks"); providerFixture.AddDatabaseName(ProviderType.MySql, "mysqladventureworks"); // 2) Add tables providerFixture.AddTables(ProviderType.Sql, sqlTables); providerFixture.AddTables(ProviderType.MySql, mySqlTables); // 3) Add runs // Enable the test to run on TCP / HTTP and on various client // Example : EnableClientType((ProviderType.Sql, NetworkType.Tcp), ProviderType.Sql | ProviderType.MySql | ProviderType.Sqlite) // 1st arg : (NetworkType.Tcp, ProviderType.Sql) : For a server provider SQL and on TCP // 2nd arg : ProviderType.Sql | ProviderType.MySql | ProviderType.Sqlite : Enable tests on clients of type Sql, MySql and Sqlite // SQL Server provider providerFixture.AddRun((ProviderType.Sql, NetworkType.Tcp), ProviderType.Sql | ProviderType.Sqlite); providerFixture.AddRun((ProviderType.Sql, NetworkType.Http), ProviderType.Sqlite); // My SQL (disable http to go faster on app veyor) providerFixture.AddRun((ProviderType.MySql, NetworkType.Tcp),ProviderType.MySql | ProviderType.Sqlite); // Exception for App veyor to be more efficient :) if (!IsOnAppVeyor) providerFixture.AddRun((ProviderType.MySql, NetworkType.Http), ProviderType.Sql |ProviderType.MySql | ProviderType.Sqlite); } ``` -------------------------------- ### Synchronize with Custom Setup (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Scopes.rst Shows an example of initializing a SyncAgent with different data providers and defining a custom synchronization setup with specific tables. It then performs the synchronization and retrieves the result. ```csharp var serverProvider = new SqlSyncChangeTrackingProvider(serverConnectionString); var clientProvider = new SqliteSyncProvider(clientConnectionString); var setup = new SyncSetup("ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" ); var agent = new SyncAgent(clientProvider, serverProvider); var s1 = await agent.SynchronizeAsync(setup); ``` -------------------------------- ### Install Dotmim.Sync CLI Tool Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/CLI.md This code snippet shows how to configure a .csproj file to install the Dotmim.Sync CLI tool as a .NET Core CLI tool. This enables the use of `dotnet sync` commands. It requires a .NET Core SDK environment. ```xml Exe netcoreapp2.0 ``` -------------------------------- ### Create Sync Setup and Synchronize with Filters Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/ScopeClients.rst Demonstrates how to define synchronization setup including tables and filters, and then perform synchronization with specific parameter values. This process results in the creation of independent scope clients for each set of parameters. ```csharp var setup = new SyncSetup("ProductCategory", "Product", "Employee"); setup.Tables[productCategoryTableName].Columns .AddRange("ProductCategoryId", "Name", "rowguid", "ModifiedDate"); setup.Filters.Add("ProductCategory", "ProductCategoryId"); setup.Filters.Add("Product", "ProductCategoryId"); var pMount = new SyncParameters(("ProductCategoryId", "MOUNTB")); var pRoad = new SyncParameters(("ProductCategoryId", "ROADFR")); var agent = new SyncAgent(client.Provider, Server.Provider); var r1 = await agent.SynchronizeAsync("v1", setup, pMount); var r2 = await agent.SynchronizeAsync("v1", setup, pRoad); ``` -------------------------------- ### Install Dotmim.Sync Database Packages (Bash) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Overview.rst Installs necessary Dotmim.Sync packages for different database providers using the dotnet CLI. These packages are required on both server and client sides depending on the synchronization scenario. ```bash dotnet add package Dotmim.Sync.SqlServer dotnet add package Dotmim.Sync.SqlServer.ChangeTracking dotnet add package Dotmim.Sync.MySql dotnet add package Dotmim.Sync.MariaDB dotnet add package Dotmim.Sync.Sqlite ``` -------------------------------- ### Restore Packages and Install CLI Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/CLI.md This command demonstrates how to restore NuGet packages for a .csproj file, which includes installing the Dotmim.Sync CLI tool. This is a prerequisite for using the CLI commands. The output shows the restoration progress and installation of various sync-related packages. ```bash $ dotnet restore Restoring packages for /mnt/c/Sync cli/synccli.csproj... Restoring packages for /mnt/c/Sync cli/synccli.csproj... Generating MSBuild file /mnt/c/Sync cli/obj/synccli.csproj.nuget.g.props. Generating MSBuild file /mnt/c/Sync cli/obj/synccli.csproj.nuget.g.targets. Restore completed in 825,56 ms for /mnt/c/Sync cli/synccli.csproj. Installing System.Data.Common. Installing System.Reflection.TypeExtensions. Installing System.Text.Json. Installing Dotmim.Sync.Core. Installing YamlDotNet. Installing Dotmim.Sync.Web. Installing Dotmim.Sync.SqlServer. Installing Dotmim.Sync.Sqlite. Installing Dotmim.Sync.Tools. Restore completed in 27,54 sec for /mnt/c/Sync cli/synccli.csproj. ``` -------------------------------- ### New Client Database Sync Output (Bash) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Snapshot.rst This is an example log output from a new client initiating a synchronization. It details the sequence of events, including session start, scope loading, table schema application, and changes applied to various tables. ```bash BeginSession 14:00:22.651 ScopeLoading 14:00:22.790 Id:b3d33500-ee06-427a-bccc-7518a9dfec93 LastSync: LastSyncDuration:0 TableSchemaApplied 14:00:26.95 TableName: ProductCategory Provision:All TableSchemaApplied 14:00:26.234 TableName: ProductModel Provision:All TableSchemaApplied 14:00:26.415 TableName: Product Provision:All TableSchemaApplied 14:00:26.466 TableName: Address Provision:All TableSchemaApplied 14:00:26.578 TableName: Customer Provision:All TableSchemaApplied 14:00:26.629 TableName: CustomerAddress Provision:All TableSchemaApplied 14:00:26.777 TableName: SalesOrderHeader Provision:All TableSchemaApplied 14:00:26.830 TableName: SalesOrderDetail Provision:All SchemaApplied 14:00:26.831 Tables count:8 Provision:All TableChangesApplied 14:00:28.101 ProductCategory State:Modified Applied:41 Failed:0 TableChangesApplied 14:00:28.252 ProductModel State:Modified Applied:128 Failed:0 TableChangesApplied 14:00:28.449 Product State:Modified Applied:201 Failed:0 TableChangesApplied 14:00:28.535 Product State:Modified Applied:295 Failed:0 TableChangesApplied 14:00:28.686 Address State:Modified Applied:450 Failed:0 TableChangesApplied 14:00:28.874 Customer State:Modified Applied:847 Failed:0 TableChangesApplied 14:00:29.28 CustomerAddress State:Modified Applied:417 Failed:0 TableChangesApplied 14:00:29.165 SalesOrderHeader State:Modified Applied:32 Failed:0 ``` -------------------------------- ### Configure Table Schema using SyncSetup Instance Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Configuration.rst Shows how to set schema names for individual tables after creating a SyncSetup instance. This provides a more granular approach to schema configuration, allowing specific schemas to be assigned to different tables within the synchronization setup. ```csharp var setup = new SyncSetup ("ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress"); setup.Tables["ProductCategory"].SchemaName = "SalesLt"; setup.Tables["ProductModel"].SchemaName = "SalesLt"; setup.Tables["Product"].SchemaName = "SalesLt"; ``` -------------------------------- ### Synchronizing With Batch Mode Enabled in C# Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Configuration.rst This C# code example shows how to perform synchronization with batch mode enabled. It involves creating a SyncOptions object with a specified BatchSize and passing it to the SyncAgent constructor. The example also includes progress reporting using SynchronousProgress to log synchronization stages and messages. The Fiddler trace image (not included here) would typically show smaller, chunked HTTP requests, indicating batch processing. ```csharp // ---------------------------------- // Client side // ---------------------------------- var clientOptions = new SyncOptions { BatchSize = 500 }; var agent = new SyncAgent(clientProvider, proxyClientProvider, clientOptions); var progress = new SynchronousProgress(pa => Console.WriteLine(String.Format("{0} -{1}\t {2}", pa.Context.SessionId, pa.Context.SyncStage, pa.Message))); var s = await agent.SynchronizeAsync(progress); Console.WriteLine(s); ``` -------------------------------- ### Sync Controller Example - C# Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Web.rst An example of a basic SyncController for ASP.NET Core that handles synchronization requests. It is set up as an API controller with a route and relies on dependency injection for the WebServerAgent. The POST method is intended to handle synchronization requests via HandleRequestAsync. ```csharp [ApiController] [Route("api/[controller]")] public class SyncController : ControllerBase { ``` -------------------------------- ### Client HTTP Interceptor Output Example (Bash) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Interceptors.rst Provides an example of the console output generated by the client-side HTTP interceptors. This output illustrates the sequence of events during a synchronization process, including sending client requests, receiving server responses, and the transmission of changes with batch information and row counts. ```bash Sending Client Request. Receiving Server Response Sending Client Request. Receiving Server Response Sending Client Changes[localhost] Sending All Changes. Rows:0 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (1/11). Rows:658 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (2/11). Rows:321 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (3/11). Rows:29 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (4/11). Rows:33 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (5/11). Rows:39 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (6/11). Rows:55 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (7/11). Rows:49 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (8/11). Rows:32 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (9/11). Rows:758 Sending Client Request. Receiving Server Response Getting Server Changes[localhost] Getting Batch Changes. (10/11). Rows:298 Sending Client Request. Receiving Server Response ``` -------------------------------- ### Example YAML Structure for Dotmim Sync Project Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/CLI.md Provides a sample YAML file structure for defining a Dotmim Sync project. It includes project name, provider configurations (SQL Server and SQLite), table synchronization settings, and various operational configurations. ```yaml project: projectsync01 providers: - providerType: SqlSyncProvider connectionString : "Data Source=(localdb)\MSSQLLocalDB; Initial Catalog=AdventureWorks;Integrated Security=true;" syncType: Server - providerType: SqliteSyncProvider connectionString : "adWorks.db" syncType: Client tables: - name : ProductCategory schema : dbo syncDirection : bidirectional - name : Product schema : dbo syncDirection : bidirectional configuration: - conflictResolution : ServerWins - downloadBatchSizeInKB : 1000 - batchDirectory : "C:\\tmp" - serializationFormat : json - useBulkOperations : true ``` -------------------------------- ### Example CustomConverter Implementation Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/SerializerConverter.rst Provides a concrete implementation of the IConverter interface. This example shows how to encode/decode a specific column ('ThumbNailPhoto') and convert DateTime values to/from ticks for the 'Product' table. ```csharp public class CustomConverter : IConverter { public string Key => "cuscom"; public void BeforeSerialize(SyncRow row) { // Each row belongs to a Table with its own Schema // Easy to filter if needed if (row.Table.TableName != "Product") return; // Encode a specific column, named "ThumbNailPhoto" if (row["ThumbNailPhoto"] != null) row["ThumbNailPhoto"] = Convert.ToBase64String((byte[])row["ThumbNailPhoto"]); // Convert all DateTime columns to ticks foreach (var col in row.Table.Columns.Where(c => c.GetDataType() == typeof(DateTime))) { if (row[col.ColumnName] != null) row[col.ColumnName] = ((DateTime)row[col.ColumnName]).Ticks; } } public void AfterDeserialized(SyncRow row) { // Only convert for table Product if (row.Table.TableName != "Product") return; // Decode photo row["ThumbNailPhoto"] = Convert.FromBase64String((string)row["ThumbNailPhoto"]); // Convert all DateTime back from ticks foreach (var col in row.Table.Columns.Where(c => c.GetDataType() == typeof(DateTime))) { if (row[col.ColumnName] != null) row[col.ColumnName] = new DateTime(Convert.ToInt64(row[col.ColumnName])); } } } ``` -------------------------------- ### Configure ASP.NET Sync Server with SQL Provider in C# Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Configuration.rst This C# code demonstrates the configuration of Dotmim Sync as a server hub within an ASP.NET Core application using dependency injection. It includes setting up the necessary services, defining the tables to be synchronized, configuring the SyncSetup with prefixes/suffixes, and registering the SqlSyncProvider as the server hub. This setup is essential for enabling HTTP mode synchronization. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddDistributedMemoryCache(); services.AddSession(options => options.IdleTimeout = TimeSpan.FromMinutes(30)); // Get a connection string for your server data source var connectionString = Configuration.GetSection("ConnectionStrings")["DefaultConnection"]; // Create the setup used for your sync process var tables = new string[] {"ProductCategory", "ProductDescription", "ProductModel", "Product", "ProductModelProductDescription", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" }; var setup = new SyncSetup(tables) { StoredProceduresPrefix = "s", StoredProceduresSuffix = "", TrackingTablesPrefix = "t", TrackingTablesSuffix = "", TriggersPrefix = "", TriggersSuffix = "t" }; // add a SqlSyncProvider acting as the server hub services.AddSyncServer(connectionString, setup); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); app.UseHttpsRedirection(); app.UseRouting(); app.UseSession(); app.UseEndpoints(endpoints => endpoints.MapControllers()); } ``` -------------------------------- ### Multi-Scope Synchronization Example Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Scopes.rst Demonstrates synchronizing different sets of tables independently using multiple SyncSetup instances and scope names with a SyncAgent. Includes progress reporting during synchronization. ```csharp // Create 2 Sql Sync providers var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName)); var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName)); // Create 2 setup var setupProducts = new SyncSetup("ProductCategory", "ProductModel", "Product"); var setupCustomers = new SyncSetup("Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail"); // Create an agent var agent = new SyncAgent(clientProvider, serverProvider); // Using the Progress pattern to handle progession during the synchronization var progress = new SynchronousProgress(s => Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}"); ); Console.WriteLine("Hit 1 for sync Products. Hit 2 for sync customers and sales"); var k = Console.ReadKey().Key; if (k == ConsoleKey.D1) { Console.WriteLine("Sync Products:"); var s1 = await agent.SynchronizeAsync("products", setupProducts, progress); Console.WriteLine(s1); } else { Console.WriteLine("Sync Customers and Sales:"); var s1 = await agent.SynchronizeAsync("customers", setupCustomers, progress); Console.WriteLine(s1); } ``` -------------------------------- ### ASP.NET Core Web API Sync Server Setup (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Snapshot.rst This snippet shows the configuration of a Dotmim Sync server within an ASP.NET Core Web API. It includes setting up controllers, distributed cache, session, defining SyncOptions with a snapshots directory, and registering the SqlSyncProvider with connection string, setup, and options. ```csharp public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddDistributedMemoryCache(); services.AddSession(options => options.IdleTimeout = TimeSpan.FromMinutes(30)); // Get a connection string for your server data source var connectionString = Configuration.GetSection("ConnectionStrings")["DefaultConnection"]; // Set the web server Options var options = new SyncOptions() { SnapshotsDirectory = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Snapshots") }; // Create the setup used for your sync process var tables = new string[] {"ProductCategory", "ProductDescription", "ProductModel", "Product", "ProductModelProductDescription", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" }; var setup = new SyncSetup(tables); // add a SqlSyncProvider acting as the server hub services.AddSyncServer(connectionString, setup, options); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); app.UseHttpsRedirection(); app.UseRouting(); app.UseSession(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } ``` -------------------------------- ### SynchronizeAsync with Table Array vs. SyncSetup Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Configuration.rst Demonstrates two equivalent ways to initiate synchronization using the SynchronizeAsync method. The first method takes an array of table names, while the second uses a pre-configured SyncSetup object, offering more control over the synchronization process. ```csharp var tables = new string[] {"ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" }; var agent = new SyncAgent(clientProvider, serverProvider); var r = await agent.SynchronizeAsync(tables); ``` ```csharp var setup = new SyncSetup("ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail"); var agent = new SyncAgent(clientProvider, serverProvider); var r = await agent.SynchronizeAsync(setup); ``` -------------------------------- ### Launch Database Synchronization Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/CLI.md This command initiates the database synchronization process using the Dotmim.Sync CLI. After a project has been configured, this command starts the sync session, selects changes, applies them, and completes the session. It provides feedback on the progress, including the number of tables involved and changes applied. ```bash $ dotnet sync -s Sync Start Begin Session. Ensure Configuration Configuration readed. 2 table(s) involved. Selecting changes... Changes selected : 0 Applying changes... Changes applied : 1234 End Session. ``` -------------------------------- ### Initial Synchronization with SyncSetup Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Synchronize.rst Illustrates a straightforward sample of performing an initial synchronization using SyncAgent with a defined SyncSetup. This setup specifies which tables are included in the synchronization. The output shows the synchronization results, including the number of uploaded and downloaded changes. ```csharp SqlSyncProvider serverProvider = new SqlSyncProvider(GetDatabaseConnectionString("AdventureWorks")); SqlSyncProvider clientProvider = new SqlSyncProvider(GetDatabaseConnectionString("Client")); var setup = new SyncSetup("ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail"); SyncAgent agent = new SyncAgent(clientProvider, serverProvider); var syncContext = await agent.SynchronizeAsync(setup); Console.WriteLine(syncContext); ``` -------------------------------- ### Handle Conflicting Setup with Interceptor Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Provision.rst Automates schema update resolution by intercepting conflicting setup events. The `OnConflictingSetup` interceptor allows clients to automatically provision new server scopes or define actions like continuing, aborting, or rolling back synchronization. This is useful when direct client application updates are not feasible. ```csharp // ----------------------------------------------------------------- // Client side // ----------------------------------------------------------------- agent.LocalOrchestrator.OnConflictingSetup(async args => { if (args.ServerScopeInfo != null) { args.ClientScopeInfo = await localOrchestrator.ProvisionAsync(args.ServerScopeInfo, overwrite: true); // this action will let the sync continue args.Action = ConflictingSetupAction.Continue; return; } // if we raise this step, just and the sync without raising an error args.Action = ConflictingSetupAction.Abort; // The Rollback Action will raise an error // args.Action = ConflictingSetupAction.Rollback; }); ``` -------------------------------- ### Filter Columns for Synchronization Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Configuration.rst Demonstrates how to filter specific columns for synchronization on a per-table basis using the SyncSetup instance. This allows for selective synchronization of data by including only necessary columns for tables like 'Customer' and 'Address'. ```csharp var setup = new SyncSetup("ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" ); // Filter columns setup.Tables["Customer"].Columns.AddRange(new string[] { "CustomerID", "EmployeeID", "NameStyle", "FirstName", "LastName" }); setup.Tables["Address"].Columns.AddRange(new string[] { "AddressID", "AddressLine1", "City", "PostalCode" }); ``` -------------------------------- ### Add Simple Filter to Setup (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Filters.rst Applies a filter to the 'Customer' table based on the 'CustomerID' column using a straightforward method. This internally creates a SetupFilter, a parameter matching the column type, and a WHERE clause comparing the parameter to the column. ```csharp setup.Filters.Add("Customer", "CustomerID"); ``` -------------------------------- ### Basic Sync Agent Initialization and Synchronization (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Provision.rst This C# code snippet demonstrates a straightforward setup for synchronizing client and server databases using SqlSyncProvider and SyncAgent. It initializes providers, defines the tables to be synced, and initiates the synchronization process. The output of the synchronization is then printed to the console. ```csharp SqlSyncProvider serverProvider = new SqlSyncProvider(GetDatabaseConnectionString("Northwind")); SqlSyncProvider clientProvider = new SqlSyncProvider(GetDatabaseConnectionString("NW1")); var setup = new SyncSetup("Customers", "Region"); var agent = new SyncAgent(clientProvider, serverProvider); var result = await agent.SynchronizeAsync(setup); Console.WriteLine(result); ``` -------------------------------- ### SyncOptions Class Definition in C# Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Configuration.rst Defines the SyncOptions class in C#, which encapsulates various settings that can be independently configured on both the client and server sides of a Dotmim Sync setup. Properties include directories for batch and snapshot storage, batch size for batch mode, and a flag for enabling verbose errors during sync operations. ```csharp /// /// This class determines all the options you can set on Client & Server, /// that could potentially be different /// public class SyncOptions { /// /// Gets or Sets the directory used for batch mode. /// Default value is [User Temp Path]/[DotmimSync] /// public string BatchDirectory { get; set; } /// /// Gets or Sets the directory where snapshots are stored. /// This value could be overwritten by server is used in an http mode /// public string SnapshotsDirectory { get; set; } /// /// Gets or Sets the size used (approximatively in kb, depending on the serializer) /// for each batch file, in batch mode. /// Default is 0 (no batch mode) /// public int BatchSize { get; set; } /// /// Gets or Sets the log level for sync operations. Default value is false. /// public bool UseVerboseErrors { get; set; } /// ``` -------------------------------- ### Advanced Sync Agent Initialization with Explicit Orchestrators (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/HowDoesItWorks.rst Shows a more explicit way to set up Dotmim.Sync synchronization by manually creating LocalOrchestrator and RemoteOrchestrator instances, then passing them to the SyncAgent. This provides greater control over the setup. ```csharp // Create 2 providers, one for MySql, one for Sqlite. var serverProvider = new MySqlSyncProvider(serverConnectionString); var clientProvider = new SqliteSyncProvider(clientConnectionString); // Setup and options define the tables and some useful options. var setup = new SyncSetup("ProductCategory", "ProductModel", "Product"); // Define a local orchestrator, using the Sqlite provider // and a remote orchestrator, using the MySql provider. var localOrchestrator = new LocalOrchestrator(clientProvider); var remoteOrchestrator = new RemoteOrchestrator(serverProvider); // Create the agent with existing orchestrators var agent = new SyncAgent(localOrchestrator, remoteOrchestrator); // Launch the sync var result = await agent.SynchronizeAsync(setup); Console.WriteLine(result); ``` -------------------------------- ### Define SyncSetup Class Structure Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Configuration.rst Defines the structure of the SyncSetup class, outlining properties for scope name, tables, filters, and naming conventions for stored procedures and tracking tables. This class is central to configuring the synchronization schema. ```csharp public class SyncSetup { /// /// Gets or Sets the scope name /// public string ScopeName { get; set; } /// /// Gets or Sets all the synced tables /// public SetupTables Tables { get; set; } /// /// Specify all filters for each table /// public SetupFilters Filters { get; set; } /// /// Specify a prefix for naming stored procedure. Default is empty string /// public string StoredProceduresPrefix { get; set; } /// /// Specify a suffix for naming stored procedures. Default is empty string /// public string StoredProceduresSuffix { get; set; } /// /// Specify a prefix for naming stored procedure. Default is empty string /// public string TriggersPrefix { get; set; } /// /// Specify a suffix for naming stored procedures. Default is empty string /// public string TriggersSuffix { get; set; } /// /// Specify a prefix for naming tracking tables. Default is empty string /// public string TrackingTablesPrefix { get; set; } /// /// Specify a suffix for naming tracking tables. /// public string TrackingTablesSuffix { get; set; } } ``` -------------------------------- ### Configure Table Sync Directions (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Synchronize.rst Demonstrates how to set specific synchronization directions for tables within a SyncSetup object. This example configures 'Customer', 'CustomerAddress', and 'Address' tables for DownloadOnly synchronization. ```csharp var syncSetup = new SyncSetup("SalesLT.ProductCategory", "SalesLT.ProductModel", "SalesLT.Product", "SalesLT.Address", "SalesLT.Customer", "SalesLT.CustomerAddress"); syncSetup.Tables["Customer"].SyncDirection = SyncDirection.DownloadOnly; syncSetup.Tables["CustomerAddress"].SyncDirection = SyncDirection.DownloadOnly; syncSetup.Tables["Address"].SyncDirection = SyncDirection.DownloadOnly; var agent = new SyncAgent(clientProvider, serverProvider); ``` -------------------------------- ### Initialize SQLCipher Sync Provider (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/SqliteEncryption.rst This C# code demonstrates how to initialize the SqliteSyncProvider with an encrypted SQLite database. It requires a connection string that includes the 'Password' parameter. ```csharp // connection string should be something like "Data Source=AdventureWorks.db;Password=..." var sqliteConnectionString = configuration.GetConnectionString("SqliteConnection"); var clientProvider = new SqliteSyncProvider(sqliteConnectionString); // You can use a SqliteConnectionStringBuilder() as well, like this: //var builder = new SqliteConnectionStringBuilder(); //builder.DataSource = "AdventureWorks.db"; //builder.Password = "..."; ``` -------------------------------- ### Client HTTP Interceptor Setup (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Interceptors.rst Demonstrates how to set up HTTP interceptors on the client side using the WebRemoteOrchestrator. These interceptors allow you to hook into the request and response lifecycle, as well as the process of sending and receiving changes. They are essential for logging, debugging, or customizing synchronization behavior. ```csharp localOrchestrator.OnHttpGettingResponse(req => Console.WriteLine("Receiving Server Response")); localOrchestrator.OnHttpSendingRequest(res =>Console.WriteLine("Sending Client Request.")); localOrchestrator.OnHttpGettingChanges(args => Console.WriteLine("Getting Server Changes" + args)); localOrchestrator.OnHttpSendingChanges(args => Console.WriteLine("Sending Client Changes" + args)); ``` -------------------------------- ### Client-Side Provisioning with Local and Remote Orchestrators Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Provision.rst This example shows how to provision a client database by relying on the server's schema. It involves creating both a LocalOrchestrator for the client and a RemoteOrchestrator to fetch the server's schema information. The local orchestrator then uses this schema to provision the client database. ```csharp // Create 2 Sql Sync providers var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName)); var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName)); // Create standard Setup and Options var setup = new SyncSetup("Address", "Customer", "CustomerAddress"); // Create a local orchestrator used to provision everything locally var localOrchestrator = new LocalOrchestrator(clientProvider); // Because we need the schema from remote side, create a remote orchestrator var remoteOrchestrator = new RemoteOrchestrator(serverProvider); // Getting the scope info from server side var serverScope = await remoteOrchestrator.GetScopeInfoAsync(); // Provision everything needed (sp, triggers, tracking tables, AND TABLES) await localOrchestrator.ProvisionAsync(serverScope); ``` -------------------------------- ### C# Dotmim Sync: Define SyncSetup with Multiple Tables Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Filters.rst This C# code defines the initial SyncSetup for Dotmim Sync, specifying the tables to be synchronized. It's the starting point for configuring synchronization, including all the tables that will be part of the sync process. ```csharp var setup = new SyncSetup(new string[] {"ProductCategory", "ProductModel", "Product", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" }); ``` -------------------------------- ### Configure Project for SQLite Encryption (XML) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/SqliteEncryption.rst This XML snippet shows how to configure your project file (.csproj) to include the required SQLite encryption packages. It overrides default references with the SQLCipher versions. ```xml Exe netcoreapp3.1 ``` -------------------------------- ### Access Deployed Raw Assets using C# Essentials Source: https://github.com/mimetis/dotmim.sync/blob/master/Samples/MAUI/MauiAppClient/Resources/Raw/AboutAssets.txt This C# code example shows how to load and read the contents of a raw asset that has been deployed with the application package. It utilizes the `FileSystem.OpenAppPackageFileAsync` method from the .NET MAUI Essentials library to access the file by its name. ```csharp async Task LoadMauiAsset() { using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); using var reader = new StreamReader(stream); var contents = reader.ReadToEnd(); } ``` -------------------------------- ### SyncController for Single Scope Configuration Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Web.rst A C# controller for handling synchronization requests. It injects a WebServerAgent and IWebHostEnvironment. The POST handler processes sync requests, and the GET handler provides configuration details, showing different output for development and production environments. ```csharp private WebServerAgent webServerAgent; private readonly IWebHostEnvironment env; // Injected thanks to Dependency Injection public SyncController(WebServerAgent webServerAgent, IWebHostEnvironment env) { this.webServerAgent = webServerAgent; this.env = env; } /// /// This POST handler is mandatory to handle all the sync process /// /// [HttpPost] public Task Post() => webServerAgent.HandleRequestAsync(this.HttpContext); /// /// This GET handler is optional. It allows you to see the configuration hosted on the server /// [HttpGet] public async Task Get() { if (env.IsDevelopment()) { await this.HttpContext.WriteHelloAsync(webServerAgent); } else { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine(""); stringBuilder.AppendLine(""); stringBuilder.AppendLine("Web Server properties"); stringBuilder.AppendLine(""); stringBuilder.AppendLine(" PRODUCTION MODE. HIDDEN INFO "); stringBuilder.AppendLine(""); await this.HttpContext.Response.WriteAsync(stringBuilder.ToString()); } } ``` -------------------------------- ### Initialize and Configure Sync Project Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/CLI.md This sequence of commands illustrates the process of creating and configuring a synchronization project using the Dotmim.Sync CLI. It includes creating a project, defining server and client providers with connection strings, and adding tables to be synchronized. The commands are executed sequentially to set up a complete sync configuration. ```bash $ dotnet sync -n syncproject01 Project syncproject01 created. $ dotnet sync syncproject01 provider -p sqlserver -c "Data Source=(localdb)..." -s server Server provider of type SqlSyncProvider saved into project syncproject01. $ dotnet sync syncproject01 provider -p sqlite -c "adWorks.db" -s client Client provider of type SqliteSyncProvider saved into project syncproject01. $ dotnet sync syncproject01 table --add ProductCategory Table ProductCategory added to project syncproject01. $ dotnet sync table --add Product Table Product added to project syncproject01. ``` -------------------------------- ### Client-Side Conflict Resolution Trick (C#) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Conflict.rst Demonstrates a client-side conflict resolution technique using a two-sync process, where conflicts are initially resolved on the server, then sent back to the client for final decision. This requires the ConflictResolutionPolicy to be set to ConflictResolutionPolicy.ServerWins. The code snippet shows the initial setup of the SyncAgent and options. ```csharp var agent = new SyncAgent(clientProvider, serverProvider, options, setup); var localOrchestrator = agent.LocalOrchestrator; var remoteOrchestrator = agent.RemoteOrchestrator; // Conflict resolution MUST BE set to ServerWins options.ConflictResolutionPolicy = ConflictResolutionPolicy.ServerWins; // From client : Remote is server, Local is client // From here, we are going to let the client decides // who is the winner of the conflict : localOrchestrator.OnApplyChangesFailed(acf => { // Check conflict is correctly set var localRow = acf.Conflict.LocalRow; var remoteRow = acf.Conflict.RemoteRow; // From that point, you can easily letting the client decides // who is the winner }); ``` -------------------------------- ### Synchronize Data with Dotmim Sync Agent Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/Progression.rst This C# code snippet demonstrates how to initiate a data synchronization process using the Dotmim Sync Agent. It utilizes the SynchronizeAsync method, specifying the setup configuration, synchronization type (Reinitialize), and a progress handler. The result of the synchronization is then printed to the console. ```csharp var s = await agent.SynchronizeAsync(setup, SyncType.Reinitialize, progress); Console.WriteLine(s); ``` -------------------------------- ### Add SQLite Encryption NuGet Packages (Bash) Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/SqliteEncryption.rst This command adds the necessary NuGet packages to your project for SQLite encryption using SQLCipher. Ensure you have the .NET CLI installed. ```bash dotnet add package Microsoft.Data.Sqlite.Core dotnet add package SQLitePCLRaw.bundle_e_sqlcipher ``` -------------------------------- ### ASP.NET Core Sync Controller Implementation Source: https://github.com/mimetis/dotmim.sync/blob/master/docs/WebSecurity.rst A C# example of a SyncController inheriting from ControllerBase in ASP.NET Core. This controller handles synchronization requests using Dotmim.Sync's WebServerAgent and includes GET and POST endpoints for sync operations and development mode information. ```csharp using Microsoft.AspNetCore.Mvc; using Dotmim.Sync.Web.Server; using Microsoft.AspNetCore.Hosting; using System.Text; using Microsoft.AspNetCore.Http; using System.Threading.Tasks; [ApiController] [Route("api/[controller]")] public class SyncController : ControllerBase { private WebServerAgent webServerAgent; private readonly IWebHostEnvironment env; // Injected thanks to Dependency Injection public SyncController(WebServerAgent webServerAgent, IWebHostEnvironment env) { this.webServerAgent = webServerAgent; this.env = env; } /// /// This POST handler is mandatory to handle all the sync process /// /// [HttpPost] public Task Post() => webServerAgent.HandleRequestAsync(this.HttpContext); /// /// This GET handler is optional. It allows you to see the configuration hosted on the server /// [HttpGet] public async Task Get() { if (env.IsDevelopment()) { await this.HttpContext.WriteHelloAsync(webServerAgent); } else { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine(""); stringBuilder.AppendLine(""); stringBuilder.AppendLine("Web Server properties"); stringBuilder.AppendLine(""); stringBuilder.AppendLine(" PRODUCTION MODE. HIDDEN INFO "); stringBuilder.AppendLine(""); await this.HttpContext.Response.WriteAsync(stringBuilder.ToString()); } } } ```