diff --git a/infra/modules/cosmos.bicep b/infra/modules/cosmos.bicep index a4704dac..1630b602 100644 --- a/infra/modules/cosmos.bicep +++ b/infra/modules/cosmos.bicep @@ -20,6 +20,88 @@ param tags object = {} /*********************************************************************************/ +var compositeIndices = [ + [ + { path: '/BestPictureWinner', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/BestPictureWinner', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Duration', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Duration', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Rating', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Rating', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/ReleaseDate', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/ReleaseDate', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Title', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Title', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/UpdatedAt', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/UpdatedAt', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Year', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Year', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Year', order: 'ascending' } + { path: '/Title', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Year', order: 'descending' } + { path: '/Title', order: 'ascending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Year', order: 'ascending' } + { path: '/Title', order: 'descending' } + { path: '/id', order: 'ascending' } + ] + [ + { path: '/Year', order: 'descending' } + { path: '/Title', order: 'descending' } + { path: '/id', order: 'ascending' } + ] +] + +/*********************************************************************************/ + + resource cosmos_account 'Microsoft.DocumentDB/databaseAccounts@2024-02-15-preview' = { name: serverName location: location @@ -70,12 +152,7 @@ resource cosmos_container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/co excludedPaths: [ { path: '/_etag/?' } ] - compositeIndexes: [ - [ - { path: '/UpdatedAt', order: 'ascending' } - { path: '/Id', order: 'ascending' } - ] - ] + compositeIndexes: compositeIndices } defaultTtl: 86400 } diff --git a/tests/CommunityToolkit.Datasync.Server.LiteDb.Test/LiteDbRepository_Tests.cs b/tests/CommunityToolkit.Datasync.Server.LiteDb.Test/LiteDbRepository_Tests.cs index b5cfd17f..160822d9 100644 --- a/tests/CommunityToolkit.Datasync.Server.LiteDb.Test/LiteDbRepository_Tests.cs +++ b/tests/CommunityToolkit.Datasync.Server.LiteDb.Test/LiteDbRepository_Tests.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using CommunityToolkit.Datasync.TestCommon; +using CommunityToolkit.Datasync.TestCommon.Databases; using CommunityToolkit.Datasync.TestCommon.Models; using LiteDB; diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveControllerTests.cs b/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveControllerTests.cs index 75215345..76de1aeb 100644 --- a/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveControllerTests.cs +++ b/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveControllerTests.cs @@ -19,10 +19,9 @@ public abstract class LiveControllerTests : BaseTest where TEntity : cl protected virtual bool CanRunLiveTests() => true; /// - /// Some tests require the ability to run math queries. This method returns true if the - /// service can run those tests. Notably, Cosmos can't run those tests. + /// The driver name - used for skipping tests when the driver doesn't support a feature. /// - protected virtual bool CanRunMathQueryTests() => true; + protected virtual string DriverName { get; } = "Default"; /// /// The actual test class must provide an implementation that retrieves the entity through diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveTestsCollection.cs b/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveTestsCollection.cs index dbd2cd3e..602c268e 100644 --- a/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveTestsCollection.cs +++ b/tests/CommunityToolkit.Datasync.Server.Test/Helpers/LiveTestsCollection.cs @@ -9,7 +9,9 @@ namespace CommunityToolkit.Datasync.Server.Test.Helpers; /// public class DatabaseFixture { - + public bool AzureSqlIsInitialized { get; set; } = false; + public bool CosmosIsInitialized { get; set; } = false; + public bool PgIsInitialized { get; set; } = false; } [CollectionDefinition("LiveTestsCollection", DisableParallelization = true)] diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Live/AzureSQL_Controller_Tests.cs b/tests/CommunityToolkit.Datasync.Server.Test/Live/AzureSQL_Controller_Tests.cs index ae4825b3..5f22df96 100644 --- a/tests/CommunityToolkit.Datasync.Server.Test/Live/AzureSQL_Controller_Tests.cs +++ b/tests/CommunityToolkit.Datasync.Server.Test/Live/AzureSQL_Controller_Tests.cs @@ -19,7 +19,6 @@ public class AzureSQL_Controller_Tests : LiveControllerTests movies; - private readonly Lazy _context; public AzureSQL_Controller_Tests(DatabaseFixture fixture, ITestOutputHelper output) : base() { @@ -27,12 +26,16 @@ public AzureSQL_Controller_Tests(DatabaseFixture fixture, ITestOutputHelper outp this.connectionString = Environment.GetEnvironmentVariable("DATASYNC_AZSQL_CONNECTIONSTRING"); if (!string.IsNullOrEmpty(this.connectionString)) { - this._context = new Lazy(() => AzureSqlDbContext.CreateContext(this.connectionString, output)); + output.WriteLine($"AzureSqlIsInitialized = {this._fixture.AzureSqlIsInitialized}"); + Context = AzureSqlDbContext.CreateContext(this.connectionString, output, clearEntities: !this._fixture.AzureSqlIsInitialized); this.movies = [.. Context.Movies.AsNoTracking()]; + this._fixture.AzureSqlIsInitialized = true; } } - private AzureSqlDbContext Context { get => this._context.Value; } + private AzureSqlDbContext Context { get; set; } + + protected override string DriverName { get; } = "AzureSQL"; protected override bool CanRunLiveTests() => !string.IsNullOrEmpty(this.connectionString); diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Live/Cosmos_Controller_Tests.cs b/tests/CommunityToolkit.Datasync.Server.Test/Live/Cosmos_Controller_Tests.cs new file mode 100644 index 00000000..f7b75ccb --- /dev/null +++ b/tests/CommunityToolkit.Datasync.Server.Test/Live/Cosmos_Controller_Tests.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using CommunityToolkit.Datasync.Server.EntityFrameworkCore; +using CommunityToolkit.Datasync.Server.Test.Helpers; +using CommunityToolkit.Datasync.TestCommon.Databases; +using Microsoft.EntityFrameworkCore; +using Xunit.Abstractions; + +namespace CommunityToolkit.Datasync.Server.Test.Live; + +[ExcludeFromCodeCoverage] +[Collection("LiveTestsCollection")] +public class Cosmos_Controller_Tests : LiveControllerTests +{ + #region Setup + private readonly DatabaseFixture _fixture; + private readonly Random random = new(); + private readonly string connectionString; + private readonly List movies; + + public Cosmos_Controller_Tests(DatabaseFixture fixture, ITestOutputHelper output) : base() + { + this._fixture = fixture; + this.connectionString = Environment.GetEnvironmentVariable("DATASYNC_COSMOS_CONNECTIONSTRING"); + if (!string.IsNullOrEmpty(this.connectionString)) + { + // Note: we don't clear entities on every run to speed up the test runs. This can only be done because + // the tests are read-only (associated with the query and get capabilities). If the test being run writes + // to the database then change clearEntities to true. + output.WriteLine($"CosmosIsInitialized = {this._fixture.CosmosIsInitialized}"); + Context = CosmosDbContext.CreateContext(this.connectionString, output, clearEntities: !this._fixture.CosmosIsInitialized); + this.movies = [.. Context.Movies.AsNoTracking()]; + this._fixture.CosmosIsInitialized = true; + } + } + + private CosmosDbContext Context { get; set; } + + protected override string DriverName { get; } = "Cosmos"; + + protected override bool CanRunLiveTests() => !string.IsNullOrEmpty(this.connectionString); + + protected override Task GetEntityAsync(string id) + => Task.FromResult(Context.Movies.AsNoTracking().SingleOrDefault(m => m.Id == id)); + + protected override Task GetEntityCountAsync() + => Task.FromResult(Context.Movies.Count()); + + protected override Task> GetPopulatedRepositoryAsync() + => Task.FromResult>(new EntityTableRepository(Context)); + + protected override Task GetRandomEntityIdAsync(bool exists) + => Task.FromResult(exists ? this.movies[this.random.Next(this.movies.Count)].Id : Guid.NewGuid().ToString()); + #endregion +} diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Live/InMemory_Controller_Tests.cs b/tests/CommunityToolkit.Datasync.Server.Test/Live/InMemory_Controller_Tests.cs new file mode 100644 index 00000000..d68264c8 --- /dev/null +++ b/tests/CommunityToolkit.Datasync.Server.Test/Live/InMemory_Controller_Tests.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using CommunityToolkit.Datasync.Server.InMemory; +using CommunityToolkit.Datasync.Server.Test.Helpers; +using CommunityToolkit.Datasync.TestCommon.Databases; + +namespace CommunityToolkit.Datasync.Server.Test.Live; + +[ExcludeFromCodeCoverage] +[Collection("LiveTestsCollection")] +public class InMemory_Controller_Tests : LiveControllerTests +{ + #region Setup + private readonly Random random = new(); + private InMemoryRepository repository; + + protected override string DriverName { get; } = "InMemory"; + + protected override Task GetEntityAsync(string id) + => Task.FromResult(this.repository.GetEntity(id)); + + protected override Task GetEntityCountAsync() + => Task.FromResult(this.repository.GetEntities().Count); + + protected override Task> GetPopulatedRepositoryAsync() + { + this.repository = new InMemoryRepository(TestCommon.TestData.Movies.OfType()); + return Task.FromResult>(this.repository); + } + + protected override Task GetRandomEntityIdAsync(bool exists) + => Task.FromResult(exists ? this.repository.GetEntities()[this.random.Next(this.repository.GetEntities().Count)].Id : Guid.NewGuid().ToString()); + #endregion +} diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Live/LiteDb_Controller_Tests.cs b/tests/CommunityToolkit.Datasync.Server.Test/Live/LiteDb_Controller_Tests.cs new file mode 100644 index 00000000..0f5198be --- /dev/null +++ b/tests/CommunityToolkit.Datasync.Server.Test/Live/LiteDb_Controller_Tests.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using CommunityToolkit.Datasync.Server.Abstractions.Http; +using CommunityToolkit.Datasync.Server.InMemory; +using CommunityToolkit.Datasync.Server.LiteDb; +using CommunityToolkit.Datasync.Server.Test.Helpers; +using CommunityToolkit.Datasync.TestCommon.Databases; +using LiteDB; + +namespace CommunityToolkit.Datasync.Server.Test.Live; + +[ExcludeFromCodeCoverage] +[Collection("LiveTestsCollection")] +public class LiteDb_Controller_Tests : LiveControllerTests, IDisposable +{ + #region Setup + private readonly Random random = new(); + private string dbFilename; + private LiteDatabase database; + private ILiteCollection collection; + private LiteDbRepository repository; + private readonly List movies = []; + + protected override Task GetEntityAsync(string id) + => Task.FromResult(this.collection.FindById(id)); + + protected override Task GetEntityCountAsync() + => Task.FromResult(this.collection.Count()); + + protected override Task> GetPopulatedRepositoryAsync() + { + this.dbFilename = Path.GetTempFileName(); + this.database = new LiteDatabase($"Filename={this.dbFilename};Connection=direct;InitialSize=0"); + this.collection = this.database.GetCollection("litedbmovies"); + + foreach (LiteDbMovie movie in TestCommon.TestData.Movies.OfType()) + { + movie.UpdatedAt = DateTimeOffset.Now; + movie.Version = Guid.NewGuid().ToByteArray(); + this.collection.Insert(movie); + this.movies.Add(movie); + } + + this.repository = new LiteDbRepository(this.database); + return Task.FromResult>(this.repository); + } + + protected override Task GetRandomEntityIdAsync(bool exists) + => Task.FromResult(exists ? this.movies[this.random.Next(this.movies.Count)].Id : Guid.NewGuid().ToString()); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + this.database?.Dispose(); + if (!string.IsNullOrEmpty(this.dbFilename)) + { + File.Delete(this.dbFilename); + } + } + } + #endregion +} diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Live/PgSQL_Controller_Tests.cs b/tests/CommunityToolkit.Datasync.Server.Test/Live/PgSQL_Controller_Tests.cs index 6a5a39d7..941d11dd 100644 --- a/tests/CommunityToolkit.Datasync.Server.Test/Live/PgSQL_Controller_Tests.cs +++ b/tests/CommunityToolkit.Datasync.Server.Test/Live/PgSQL_Controller_Tests.cs @@ -19,7 +19,6 @@ public class PgSQL_Controller_Tests : LiveControllerTests private readonly Random random = new(); private readonly string connectionString; private readonly List movies; - private readonly Lazy _context; public PgSQL_Controller_Tests(DatabaseFixture fixture, ITestOutputHelper output) : base() { @@ -27,12 +26,16 @@ public PgSQL_Controller_Tests(DatabaseFixture fixture, ITestOutputHelper output) this.connectionString = Environment.GetEnvironmentVariable("DATASYNC_PGSQL_CONNECTIONSTRING"); if (!string.IsNullOrEmpty(this.connectionString)) { - this._context = new Lazy(() => PgDbContext.CreateContext(this.connectionString, output)); + output.WriteLine($"PgIsInitialized = {this._fixture.PgIsInitialized}"); + Context = PgDbContext.CreateContext(this.connectionString, output, clearEntities: !this._fixture.PgIsInitialized); this.movies = Context.Movies.AsNoTracking().ToList(); + this._fixture.PgIsInitialized = true; } } - private PgDbContext Context { get => this._context.Value; } + private PgDbContext Context { get; set; } + + protected override string DriverName { get; } = "PgSQL"; protected override bool CanRunLiveTests() => !string.IsNullOrEmpty(this.connectionString); diff --git a/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj b/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj index 515a6767..a846b3a4 100644 --- a/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj +++ b/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj @@ -25,5 +25,6 @@ + diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Databases/AzureSql/AzureSqlDbContext.cs b/tests/CommunityToolkit.Datasync.TestCommon/Databases/AzureSql/AzureSqlDbContext.cs index 4f6eb850..49d7ac9f 100644 --- a/tests/CommunityToolkit.Datasync.TestCommon/Databases/AzureSql/AzureSqlDbContext.cs +++ b/tests/CommunityToolkit.Datasync.TestCommon/Databases/AzureSql/AzureSqlDbContext.cs @@ -11,7 +11,7 @@ namespace CommunityToolkit.Datasync.TestCommon.Databases; [ExcludeFromCodeCoverage] public class AzureSqlDbContext(DbContextOptions options) : BaseDbContext(options) { - public static AzureSqlDbContext CreateContext(string connectionString, ITestOutputHelper output = null) + public static AzureSqlDbContext CreateContext(string connectionString, ITestOutputHelper output = null, bool clearEntities = true) { if (string.IsNullOrEmpty(connectionString)) { @@ -23,12 +23,12 @@ public static AzureSqlDbContext CreateContext(string connectionString, ITestOutp .EnableLogging(output); AzureSqlDbContext context = new(optionsBuilder.Options); - context.InitializeDatabase(); + context.InitializeDatabase(clearEntities); context.PopulateDatabase(); return context; } - internal void InitializeDatabase() + internal void InitializeDatabase(bool clearEntities) { const string datasyncTrigger = @" CREATE OR ALTER TRIGGER [dbo].[{0}_datasync] ON [dbo].[{0}] AFTER INSERT, UPDATE AS @@ -44,8 +44,12 @@ internal void InitializeDatabase() "; Database.EnsureCreated(); - ExecuteRawSqlOnEachEntity("DELETE FROM [dbo].[{0}]"); ExecuteRawSqlOnEachEntity(datasyncTrigger); + + if (clearEntities) + { + ExecuteRawSqlOnEachEntity("DELETE FROM [dbo].[{0}]"); + } } protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Databases/Base/BaseDbContext.cs b/tests/CommunityToolkit.Datasync.TestCommon/Databases/Base/BaseDbContext.cs index 0b40c2e3..73f06a1a 100644 --- a/tests/CommunityToolkit.Datasync.TestCommon/Databases/Base/BaseDbContext.cs +++ b/tests/CommunityToolkit.Datasync.TestCommon/Databases/Base/BaseDbContext.cs @@ -48,8 +48,15 @@ protected void ExecuteRawSqlOnEachEntity(string format) /// /// Populates the database with the core set of movies. Ensures that we have the same data for all tests. /// + [SuppressMessage("Performance", "CA1827:Do not use Count() or LongCount() when Any() can be used", Justification = "CosmosDB does not support .Any()")] protected void PopulateDatabase() { + bool hasEntities = Movies.Count() > 0; + if (hasEntities) + { + return; + } + List movies = [.. TestData.Movies.OfType()]; MovieIds = movies.ConvertAll(m => m.Id); diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Databases/CosmosDb/CosmosDbContext.cs b/tests/CommunityToolkit.Datasync.TestCommon/Databases/CosmosDb/CosmosDbContext.cs index e9cb42d3..3ca7f146 100644 --- a/tests/CommunityToolkit.Datasync.TestCommon/Databases/CosmosDb/CosmosDbContext.cs +++ b/tests/CommunityToolkit.Datasync.TestCommon/Databases/CosmosDb/CosmosDbContext.cs @@ -12,7 +12,7 @@ namespace CommunityToolkit.Datasync.TestCommon.Databases; [ExcludeFromCodeCoverage] public class CosmosDbContext(DbContextOptions options) : BaseDbContext(options) { - public static CosmosDbContext CreateContext(string connectionString, ITestOutputHelper output = null) + public static CosmosDbContext CreateContext(string connectionString, ITestOutputHelper output = null, bool clearEntities = true) { if (string.IsNullOrEmpty(connectionString)) { @@ -24,15 +24,18 @@ public static CosmosDbContext CreateContext(string connectionString, ITestOutput .EnableLogging(output); CosmosDbContext context = new(optionsBuilder.Options); - context.InitializeDatabase(); + context.InitializeDatabase(clearEntities); context.PopulateDatabase(); return context; } - internal void InitializeDatabase() + internal void InitializeDatabase(bool clearEntities) { - RemoveRange(Movies.ToList()); - SaveChanges(); + if (clearEntities) + { + RemoveRange(Movies.ToList()); + SaveChanges(); + } } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) @@ -48,6 +51,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) builder.HasNoDiscriminator(); builder.HasPartitionKey(model => model.Id); builder.Property(model => model.EntityTag).IsETagConcurrency(); + + // Note that the composite indices needed for Cosmos are defined in the bicep + // See infra/modules/cosmos.bicep + }); base.OnModelCreating(modelBuilder); } diff --git a/tests/CommunityToolkit.Datasync.Server.LiteDb.Test/Helpers/LiteDbMovie.cs b/tests/CommunityToolkit.Datasync.TestCommon/Databases/LiteDb/LiteDbMovie.cs similarity index 94% rename from tests/CommunityToolkit.Datasync.Server.LiteDb.Test/Helpers/LiteDbMovie.cs rename to tests/CommunityToolkit.Datasync.TestCommon/Databases/LiteDb/LiteDbMovie.cs index 6d1c9f56..89a7c6eb 100644 --- a/tests/CommunityToolkit.Datasync.Server.LiteDb.Test/Helpers/LiteDbMovie.cs +++ b/tests/CommunityToolkit.Datasync.TestCommon/Databases/LiteDb/LiteDbMovie.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using CommunityToolkit.Datasync.Server.LiteDb; using CommunityToolkit.Datasync.TestCommon.Models; using System.ComponentModel.DataAnnotations; -namespace CommunityToolkit.Datasync.Server.LiteDb.Test; +namespace CommunityToolkit.Datasync.TestCommon.Databases; [ExcludeFromCodeCoverage] public class LiteDbMovie : LiteDbTableData, IMovie, IEquatable diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Databases/Postgresql/PgDbContext.cs b/tests/CommunityToolkit.Datasync.TestCommon/Databases/Postgresql/PgDbContext.cs index 9d56cd47..508ca0b9 100644 --- a/tests/CommunityToolkit.Datasync.TestCommon/Databases/Postgresql/PgDbContext.cs +++ b/tests/CommunityToolkit.Datasync.TestCommon/Databases/Postgresql/PgDbContext.cs @@ -10,7 +10,7 @@ namespace CommunityToolkit.Datasync.TestCommon.Databases; [ExcludeFromCodeCoverage] public class PgDbContext(DbContextOptions options) : BaseDbContext(options) { - public static PgDbContext CreateContext(string connectionString, ITestOutputHelper output = null) + public static PgDbContext CreateContext(string connectionString, ITestOutputHelper output = null, bool clearEntities = true) { if (string.IsNullOrEmpty(connectionString)) { @@ -22,12 +22,12 @@ public static PgDbContext CreateContext(string connectionString, ITestOutputHelp .EnableLogging(output); PgDbContext context = new(optionsBuilder.Options); - context.InitializeDatabase(); + context.InitializeDatabase(clearEntities); context.PopulateDatabase(); return context; } - internal void InitializeDatabase() + internal void InitializeDatabase(bool clearEntities) { const string datasyncTrigger = @" CREATE OR REPLACE FUNCTION {0}_datasync() RETURNS trigger AS $$ @@ -47,8 +47,12 @@ FOR EACH ROW EXECUTE PROCEDURE "; Database.EnsureCreated(); - ExecuteRawSqlOnEachEntity(@"DELETE FROM ""{0}"""); ExecuteRawSqlOnEachEntity(datasyncTrigger); + + if (clearEntities) + { + ExecuteRawSqlOnEachEntity(@"DELETE FROM ""{0}"""); + } } protected override void OnModelCreating(ModelBuilder modelBuilder)