diff --git a/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs b/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs
index 238d18324a1..c1580503337 100644
--- a/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs
+++ b/src/EFCore.Cosmos/Diagnostics/CosmosEventId.cs
@@ -25,6 +25,7 @@ public static class CosmosEventId
private enum Id
{
// Database events
+ SyncNotSupported = CoreEventId.ProviderBaseId,
// Command events
ExecutingSqlQuery = CoreEventId.ProviderBaseId + 100,
@@ -36,6 +37,19 @@ private enum Id
ExecutedDeleteItem
}
+ private static readonly string DatabasePrefix = DbLoggerCategory.Database.Name + ".";
+
+ ///
+ /// Azure Cosmos DB does not support synchronous I/O. Make sure to use and correctly await only async
+ /// methods when using Entity Framework Core to access Azure Cosmos DB.
+ /// See https://aka.ms/ef-cosmos-nosync for more information.
+ ///
+ ///
+ /// This event is in the category.
+ ///
+ public static readonly EventId SyncNotSupported
+ = new((int)Id.SyncNotSupported, DatabasePrefix + Id.SyncNotSupported);
+
private static readonly string CommandPrefix = DbLoggerCategory.Database.Command.Name + ".";
///
diff --git a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs
index 2048ca35836..75834a6465c 100644
--- a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs
+++ b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggerExtensions.cs
@@ -19,6 +19,32 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Diagnostics.Internal;
///
public static class CosmosLoggerExtensions
{
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public static void SyncNotSupported(
+ this IDiagnosticsLogger diagnostics)
+ {
+ var definition = CosmosResources.LogSyncNotSupported(diagnostics);
+
+ if (diagnostics.ShouldLog(definition))
+ {
+ definition.Log(diagnostics);
+ }
+
+ if (diagnostics.NeedsEventData(definition, out var diagnosticSourceEnabled, out var simpleLogEnabled))
+ {
+ var eventData = new EventData(
+ definition,
+ (d, p) => ((EventDefinition)d).GenerateMessage());
+
+ diagnostics.DispatchEventData(definition, eventData, diagnosticSourceEnabled, simpleLogEnabled);
+ }
+ }
+
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
diff --git a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggingDefinitions.cs b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggingDefinitions.cs
index 168765dbccc..79cda1d0bea 100644
--- a/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggingDefinitions.cs
+++ b/src/EFCore.Cosmos/Diagnostics/Internal/CosmosLoggingDefinitions.cs
@@ -66,4 +66,12 @@ public class CosmosLoggingDefinitions : LoggingDefinitions
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public EventDefinitionBase? LogExecutedDeleteItem;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public EventDefinitionBase? LogSyncNotSupported;
}
diff --git a/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs
index 6abe47427c8..3824a31fc4d 100644
--- a/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs
+++ b/src/EFCore.Cosmos/Extensions/CosmosDbContextOptionsExtensions.cs
@@ -52,6 +52,8 @@ public static DbContextOptionsBuilder UseCosmos(
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
Check.NotNull(cosmosOptionsAction, nameof(cosmosOptionsAction));
+ ConfigureWarnings(optionsBuilder);
+
cosmosOptionsAction.Invoke(new CosmosDbContextOptionsBuilder(optionsBuilder));
return optionsBuilder;
@@ -118,6 +120,8 @@ public static DbContextOptionsBuilder UseCosmos(
.WithAccountKey(accountKey)
.WithDatabaseName(databaseName);
+ ConfigureWarnings(optionsBuilder);
+
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
cosmosOptionsAction?.Invoke(new CosmosDbContextOptionsBuilder(optionsBuilder));
@@ -186,6 +190,8 @@ public static DbContextOptionsBuilder UseCosmos(
.WithTokenCredential(tokenCredential)
.WithDatabaseName(databaseName);
+ ConfigureWarnings(optionsBuilder);
+
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
cosmosOptionsAction?.Invoke(new CosmosDbContextOptionsBuilder(optionsBuilder));
@@ -247,10 +253,25 @@ public static DbContextOptionsBuilder UseCosmos(
.WithConnectionString(connectionString)
.WithDatabaseName(databaseName);
+ ConfigureWarnings(optionsBuilder);
+
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
cosmosOptionsAction?.Invoke(new CosmosDbContextOptionsBuilder(optionsBuilder));
return optionsBuilder;
}
+
+ private static void ConfigureWarnings(DbContextOptionsBuilder optionsBuilder)
+ {
+ var coreOptionsExtension
+ = optionsBuilder.Options.FindExtension()
+ ?? new CoreOptionsExtension();
+
+ coreOptionsExtension = coreOptionsExtension.WithWarningsConfiguration(
+ coreOptionsExtension.WarningsConfiguration.TryWithExplicit(
+ CosmosEventId.SyncNotSupported, WarningBehavior.Throw));
+
+ ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(coreOptionsExtension);
+ }
}
diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs
index 773f416d117..e7561a9f10a 100644
--- a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs
+++ b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs
@@ -586,5 +586,30 @@ public static FallbackEventDefinition LogExecutedReadNext(IDiagnosticsLogger log
return (EventDefinition)definition;
}
+
+ ///
+ /// Azure Cosmos DB does not support synchronous I/O. Make sure to use and correctly await only async methods when using Entity Framework Core to access Azure Cosmos DB. See https://aka.ms/ef-cosmos-nosync for more information.
+ ///
+ public static EventDefinition LogSyncNotSupported(IDiagnosticsLogger logger)
+ {
+ var definition = ((Diagnostics.Internal.CosmosLoggingDefinitions)logger.Definitions).LogSyncNotSupported;
+ if (definition == null)
+ {
+ definition = NonCapturingLazyInitializer.EnsureInitialized(
+ ref ((Diagnostics.Internal.CosmosLoggingDefinitions)logger.Definitions).LogSyncNotSupported,
+ logger,
+ static logger => new EventDefinition(
+ logger.Options,
+ CosmosEventId.SyncNotSupported,
+ LogLevel.Error,
+ "CosmosEventId.SyncNotSupported",
+ level => LoggerMessage.Define(
+ level,
+ CosmosEventId.SyncNotSupported,
+ _resourceManager.GetString("LogSyncNotSupported")!)));
+ }
+
+ return (EventDefinition)definition;
+ }
}
}
diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.resx b/src/EFCore.Cosmos/Properties/CosmosStrings.resx
index e4494aa5e7f..e5815bbdd9b 100644
--- a/src/EFCore.Cosmos/Properties/CosmosStrings.resx
+++ b/src/EFCore.Cosmos/Properties/CosmosStrings.resx
@@ -1,17 +1,17 @@
-
@@ -187,6 +187,10 @@
Executing SQL query for container '{containerId}' in partition '{partitionKey}' [Parameters=[{parameters}]]{newLine}{commandText}
Information CosmosEventId.ExecutingSqlQuery string string? string string string
+
+ Azure Cosmos DB does not support synchronous I/O. Make sure to use and correctly await only async methods when using Entity Framework Core to access Azure Cosmos DB. See https://aka.ms/ef-cosmos-nosync for more information.
+ Error CosmosEventId.SyncNotSupported
+
'Reverse' could not be translated to the server because there is no ordering on the server side.
diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs
index 3bd43272772..1c1fbfb30fa 100644
--- a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs
+++ b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs
@@ -41,6 +41,7 @@ public class CosmosClientWrapper : ICosmosClientWrapper
private readonly string _databaseId;
private readonly IExecutionStrategy _executionStrategy;
private readonly IDiagnosticsLogger _commandLogger;
+ private readonly IDiagnosticsLogger _databaseLogger;
private readonly bool? _enableContentResponseOnWrite;
static CosmosClientWrapper()
@@ -61,7 +62,8 @@ public CosmosClientWrapper(
ISingletonCosmosClientWrapper singletonWrapper,
IDbContextOptions dbContextOptions,
IExecutionStrategy executionStrategy,
- IDiagnosticsLogger commandLogger)
+ IDiagnosticsLogger commandLogger,
+ IDiagnosticsLogger databaseLogger)
{
var options = dbContextOptions.FindExtension();
@@ -69,6 +71,7 @@ public CosmosClientWrapper(
_databaseId = options!.DatabaseName;
_executionStrategy = executionStrategy;
_commandLogger = commandLogger;
+ _databaseLogger = databaseLogger;
_enableContentResponseOnWrite = options.EnableContentResponseOnWrite;
}
@@ -82,7 +85,11 @@ private CosmosClient Client
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public virtual bool CreateDatabaseIfNotExists(ThroughputProperties? throughput)
- => _executionStrategy.Execute((throughput, this), CreateDatabaseIfNotExistsOnce, null);
+ {
+ _databaseLogger.SyncNotSupported();
+
+ return _executionStrategy.Execute((throughput, this), CreateDatabaseIfNotExistsOnce, null);
+ }
private static bool CreateDatabaseIfNotExistsOnce(
DbContext? context,
@@ -121,7 +128,11 @@ private static async Task CreateDatabaseIfNotExistsOnceAsync(
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public virtual bool DeleteDatabase()
- => _executionStrategy.Execute(this, DeleteDatabaseOnce, null);
+ {
+ _databaseLogger.SyncNotSupported();
+
+ return _executionStrategy.Execute(this, DeleteDatabaseOnce, null);
+ }
private static bool DeleteDatabaseOnce(
DbContext? context,
@@ -162,7 +173,11 @@ private static async Task DeleteDatabaseOnceAsync(
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
public virtual bool CreateContainerIfNotExists(ContainerProperties properties)
- => _executionStrategy.Execute((properties, this), CreateContainerIfNotExistsOnce, null);
+ {
+ _databaseLogger.SyncNotSupported();
+
+ return _executionStrategy.Execute((properties, this), CreateContainerIfNotExistsOnce, null);
+ }
private static bool CreateContainerIfNotExistsOnce(
DbContext context,
@@ -215,7 +230,11 @@ public virtual bool CreateItem(
string containerId,
JToken document,
IUpdateEntry entry)
- => _executionStrategy.Execute((containerId, document, entry, this), CreateItemOnce, null);
+ {
+ _databaseLogger.SyncNotSupported();
+
+ return _executionStrategy.Execute((containerId, document, entry, this), CreateItemOnce, null);
+ }
private static bool CreateItemOnce(
DbContext context,
@@ -286,7 +305,11 @@ public virtual bool ReplaceItem(
string documentId,
JObject document,
IUpdateEntry entry)
- => _executionStrategy.Execute((collectionId, documentId, document, entry, this), ReplaceItemOnce, null);
+ {
+ _databaseLogger.SyncNotSupported();
+
+ return _executionStrategy.Execute((collectionId, documentId, document, entry, this), ReplaceItemOnce, null);
+ }
private static bool ReplaceItemOnce(
DbContext context,
@@ -358,7 +381,11 @@ public virtual bool DeleteItem(
string containerId,
string documentId,
IUpdateEntry entry)
- => _executionStrategy.Execute((containerId, documentId, entry, this), DeleteItemOnce, null);
+ {
+ _databaseLogger.SyncNotSupported();
+
+ return _executionStrategy.Execute((containerId, documentId, entry, this), DeleteItemOnce, null);
+ }
private static bool DeleteItemOnce(
DbContext context,
@@ -508,6 +535,8 @@ public virtual IEnumerable ExecuteSqlQuery(
string? partitionKey,
CosmosSqlQuery query)
{
+ _databaseLogger.SyncNotSupported();
+
_commandLogger.ExecutingSqlQuery(containerId, partitionKey, query);
return new DocumentEnumerable(this, containerId, partitionKey, query);
@@ -540,6 +569,8 @@ public virtual IAsyncEnumerable ExecuteSqlQueryAsync(
string? partitionKey,
string resourceId)
{
+ _databaseLogger.SyncNotSupported();
+
_commandLogger.ExecutingReadItem(containerId, partitionKey, resourceId);
var response = _executionStrategy.Execute((containerId, partitionKey, resourceId, this), CreateSingleItemQuery, null);
diff --git a/test/EFCore.AspNet.Specification.Tests/GrpcTestBase.cs b/test/EFCore.AspNet.Specification.Tests/GrpcTestBase.cs
index 72cb364cf5c..772d861bc5c 100644
--- a/test/EFCore.AspNet.Specification.Tests/GrpcTestBase.cs
+++ b/test/EFCore.AspNet.Specification.Tests/GrpcTestBase.cs
@@ -137,7 +137,7 @@ public abstract class GrpcFixtureBase : SharedStoreFixtureBase
protected override string StoreName
=> "GrpcTest";
- protected override void Seed(GrpcContext context)
+ protected override Task SeedAsync(GrpcContext context)
{
var post = new Post
{
@@ -153,7 +153,7 @@ protected override void Seed(GrpcContext context)
context.Add(post);
- context.SaveChanges();
+ return context.SaveChangesAsync();
}
}
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs
index 35542bf2885..3f495ae7291 100644
--- a/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs
@@ -7,7 +7,8 @@ namespace Microsoft.EntityFrameworkCore;
#nullable disable
-public class BuiltInDataTypesCosmosTest(BuiltInDataTypesCosmosTest.BuiltInDataTypesCosmosFixture fixture) : BuiltInDataTypesTestBase(fixture)
+public class BuiltInDataTypesCosmosTest(BuiltInDataTypesCosmosTest.BuiltInDataTypesCosmosFixture fixture)
+ : BuiltInDataTypesTestBase(fixture)
{
[ConditionalTheory(Skip = "Issue #17246 No Explicit Convert")]
public override Task Can_filter_projection_with_inline_enum_variable(bool async)
@@ -18,33 +19,32 @@ public override Task Can_filter_projection_with_captured_enum_variable(bool asyn
=> base.Can_filter_projection_with_captured_enum_variable(async);
[ConditionalFact(Skip = "Issue #17246 No Explicit Convert")]
- public override void Can_query_with_null_parameters_using_any_nullable_data_type()
+ public override Task Can_query_with_null_parameters_using_any_nullable_data_type()
=> base.Can_query_with_null_parameters_using_any_nullable_data_type();
[ConditionalFact(Skip = "Issue #16920")]
- public override void Can_insert_and_read_back_with_string_key()
+ public override Task Can_insert_and_read_back_with_string_key()
=> base.Can_insert_and_read_back_with_string_key();
[ConditionalFact(Skip = "Issue #16920")]
- public override void Can_insert_and_read_back_with_binary_key()
+ public override Task Can_insert_and_read_back_with_binary_key()
=> base.Can_insert_and_read_back_with_binary_key();
- public override void Can_perform_query_with_max_length()
- {
+ public override Task Can_perform_query_with_max_length()
// TODO: Better translation of sequential equality #17246
- }
+ => Task.CompletedTask;
[ConditionalFact(Skip = "Issue #17670")]
- public override void Can_read_back_mapped_enum_from_collection_first_or_default()
+ public override Task Can_read_back_mapped_enum_from_collection_first_or_default()
=> base.Can_read_back_mapped_enum_from_collection_first_or_default();
[ConditionalFact(Skip = "Issue #17246")]
- public override void Can_read_back_bool_mapped_as_int_through_navigation()
+ public override Task Can_read_back_bool_mapped_as_int_through_navigation()
=> base.Can_read_back_bool_mapped_as_int_through_navigation();
- public override void Object_to_string_conversion()
+ public override async Task Object_to_string_conversion()
{
- base.Object_to_string_conversion();
+ await base.Object_to_string_conversion();
AssertSql(
"""
diff --git a/test/EFCore.Cosmos.FunctionalTests/ConcurrencyDetectorDisabledCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/ConcurrencyDetectorDisabledCosmosTest.cs
index 1e89a8cb57f..24b7cc8f91e 100644
--- a/test/EFCore.Cosmos.FunctionalTests/ConcurrencyDetectorDisabledCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/ConcurrencyDetectorDisabledCosmosTest.cs
@@ -5,13 +5,35 @@ namespace Microsoft.EntityFrameworkCore;
#nullable disable
-public class ConcurrencyDetectorDisabledCosmosTest(ConcurrencyDetectorDisabledCosmosTest.ConcurrencyDetectorCosmosFixture fixture) : ConcurrencyDetectorDisabledTestBase<
- ConcurrencyDetectorDisabledCosmosTest.ConcurrencyDetectorCosmosFixture>(fixture)
+public class ConcurrencyDetectorDisabledCosmosTest(ConcurrencyDetectorDisabledCosmosTest.ConcurrencyDetectorCosmosFixture fixture)
+ : ConcurrencyDetectorDisabledTestBase<
+ ConcurrencyDetectorDisabledCosmosTest.ConcurrencyDetectorCosmosFixture>(fixture)
{
[ConditionalTheory(Skip = "Issue #17246")]
public override Task Any(bool async)
=> base.Any(async);
+ public override Task SaveChanges(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.SaveChanges(a));
+
+ public override Task Count(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.Count(a));
+
+ public override Task Find(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.Find(a));
+
+ public override Task First(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.First(a));
+
+ public override Task Last(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.Last(a));
+
+ public override Task Single(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.Single(a));
+
+ public override Task ToList(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.ToList(a));
+
public class ConcurrencyDetectorCosmosFixture : ConcurrencyDetectorFixtureBase
{
protected override ITestStoreFactory TestStoreFactory
diff --git a/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs
index 2ba3d4e129f..344cbbe1f50 100644
--- a/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/ConfigPatternsCosmosTest.cs
@@ -8,7 +8,8 @@ namespace Microsoft.EntityFrameworkCore;
#nullable disable
-public class ConfigPatternsCosmosTest(ConfigPatternsCosmosTest.CosmosFixture fixture) : IClassFixture
+public class ConfigPatternsCosmosTest(ConfigPatternsCosmosTest.CosmosFixture fixture)
+ : IClassFixture
{
private const string DatabaseName = "ConfigPatternsCosmos";
@@ -17,7 +18,7 @@ public class ConfigPatternsCosmosTest(ConfigPatternsCosmosTest.CosmosFixture fix
[ConditionalFact]
public async Task Cosmos_client_instance_is_shared_between_contexts()
{
- await using var testDatabase = CosmosTestStore.CreateInitialized(DatabaseName);
+ await using var testDatabase = await CosmosTestStore.CreateInitializedAsync(DatabaseName);
var options = CreateOptions(testDatabase);
CosmosClient client;
@@ -34,7 +35,7 @@ public async Task Cosmos_client_instance_is_shared_between_contexts()
Assert.Same(client, context.Database.GetCosmosClient());
}
- await using var testDatabase2 = CosmosTestStore.CreateInitialized(DatabaseName, o => o.Region(Regions.AustraliaCentral));
+ await using var testDatabase2 = await CosmosTestStore.CreateInitializedAsync(DatabaseName, o => o.Region(Regions.AustraliaCentral));
options = CreateOptions(testDatabase2);
using (var context = new CustomerContext(options))
@@ -48,13 +49,13 @@ public async Task Should_not_throw_if_specified_region_is_right()
{
var regionName = Regions.AustraliaCentral;
- await using var testDatabase = CosmosTestStore.CreateInitialized(DatabaseName, o => o.Region(regionName));
+ await using var testDatabase = await CosmosTestStore.CreateInitializedAsync(DatabaseName, o => o.Region(regionName));
var options = CreateOptions(testDatabase);
var customer = new Customer { Id = 42, Name = "Theon" };
using var context = new CustomerContext(options);
- context.Database.EnsureCreated();
+ await context.Database.EnsureCreatedAsync();
await context.AddAsync(customer);
@@ -67,13 +68,13 @@ public async Task Should_throw_if_specified_region_is_wrong()
var exception = await Assert.ThrowsAsync(
async () =>
{
- await using var testDatabase = CosmosTestStore.CreateInitialized(DatabaseName, o => o.Region("FakeRegion"));
+ await using var testDatabase = await CosmosTestStore.CreateInitializedAsync(DatabaseName, o => o.Region("FakeRegion"));
var options = CreateOptions(testDatabase);
var customer = new Customer { Id = 42, Name = "Theon" };
using var context = new CustomerContext(options);
- context.Database.EnsureCreated();
+ await context.Database.EnsureCreatedAsync();
await context.AddAsync(customer);
@@ -90,13 +91,13 @@ public async Task Should_not_throw_if_specified_connection_mode_is_right()
{
var connectionMode = ConnectionMode.Direct;
- await using var testDatabase = CosmosTestStore.CreateInitialized(DatabaseName, o => o.ConnectionMode(connectionMode));
+ await using var testDatabase = await CosmosTestStore.CreateInitializedAsync(DatabaseName, o => o.ConnectionMode(connectionMode));
var options = CreateOptions(testDatabase);
var customer = new Customer { Id = 42, Name = "Theon" };
using var context = new CustomerContext(options);
- context.Database.EnsureCreated();
+ await context.Database.EnsureCreatedAsync();
await context.AddAsync(customer);
@@ -109,14 +110,14 @@ public async Task Should_throw_if_specified_connection_mode_is_wrong()
var exception = await Assert.ThrowsAsync(
async () =>
{
- await using var testDatabase = CosmosTestStore.CreateInitialized(
+ await using var testDatabase = await CosmosTestStore.CreateInitializedAsync(
DatabaseName, o => o.ConnectionMode((ConnectionMode)123456));
var options = CreateOptions(testDatabase);
var customer = new Customer { Id = 42, Name = "Theon" };
using var context = new CustomerContext(options);
- context.Database.EnsureCreated();
+ await context.Database.EnsureCreatedAsync();
await context.AddAsync(customer);
diff --git a/test/EFCore.Cosmos.FunctionalTests/CosmosConcurrencyTest.cs b/test/EFCore.Cosmos.FunctionalTests/CosmosConcurrencyTest.cs
index d60aff58720..5e04d803e0c 100644
--- a/test/EFCore.Cosmos.FunctionalTests/CosmosConcurrencyTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/CosmosConcurrencyTest.cs
@@ -14,33 +14,43 @@ public class CosmosConcurrencyTest(CosmosConcurrencyTest.CosmosFixture fixture)
[ConditionalFact]
public virtual Task Adding_the_same_entity_twice_results_in_DbUpdateException()
=> ConcurrencyTestAsync(
- ctx => ctx.Customers.Add(
- new Customer
- {
- Id = "1", Name = "CreatedTwice",
- }));
+ ctx =>
+ {
+ ctx.Customers.Add(
+ new Customer
+ {
+ Id = "1", Name = "CreatedTwice",
+ });
+ return Task.CompletedTask;
+ });
[ConditionalFact]
public virtual Task Updating_then_deleting_the_same_entity_results_in_DbUpdateConcurrencyException()
=> ConcurrencyTestAsync(
- ctx => ctx.Customers.Add(
- new Customer
- {
- Id = "2", Name = "Added",
- }),
- ctx => ctx.Customers.Single(c => c.Id == "2").Name = "Updated",
- ctx => ctx.Customers.Remove(ctx.Customers.Single(c => c.Id == "2")));
+ ctx =>
+ {
+ ctx.Customers.Add(
+ new Customer
+ {
+ Id = "2", Name = "Added",
+ });
+ return Task.CompletedTask;
+ }, async ctx => (await ctx.Customers.SingleAsync(c => c.Id == "2")).Name = "Updated",
+ async ctx => ctx.Customers.Remove(await ctx.Customers.SingleAsync(c => c.Id == "2")));
[ConditionalFact]
public virtual Task Updating_then_updating_the_same_entity_results_in_DbUpdateConcurrencyException()
=> ConcurrencyTestAsync(
- ctx => ctx.Customers.Add(
- new Customer
- {
- Id = "3", Name = "Added",
- }),
- ctx => ctx.Customers.Single(c => c.Id == "3").Name = "Updated",
- ctx => ctx.Customers.Single(c => c.Id == "3").Name = "Updated");
+ ctx =>
+ {
+ ctx.Customers.Add(
+ new Customer
+ {
+ Id = "3", Name = "Added",
+ });
+ return Task.CompletedTask;
+ }, async ctx => (await ctx.Customers.SingleAsync(c => c.Id == "3")).Name = "Updated",
+ async ctx => (await ctx.Customers.SingleAsync(c => c.Id == "3")).Name = "Updated");
[ConditionalTheory]
[InlineData(null)]
@@ -49,13 +59,14 @@ public virtual Task Updating_then_updating_the_same_entity_results_in_DbUpdateCo
public async Task Etag_is_updated_in_entity_after_SaveChanges(bool? contentResponseOnWriteEnabled)
{
var options = new DbContextOptionsBuilder(Fixture.CreateOptions())
- .UseCosmos(o =>
- {
- if (contentResponseOnWriteEnabled != null)
+ .UseCosmos(
+ o =>
{
- o.ContentResponseOnWriteEnabled(contentResponseOnWriteEnabled.Value);
- }
- })
+ if (contentResponseOnWriteEnabled != null)
+ {
+ o.ContentResponseOnWriteEnabled(contentResponseOnWriteEnabled.Value);
+ }
+ })
.Options;
var customer = new Customer
@@ -114,7 +125,7 @@ public async Task Etag_is_updated_in_entity_after_SaveChanges(bool? contentRespo
/// the database at the end of the process can be validated.
///
protected virtual Task ConcurrencyTestAsync(
- Action change)
+ Func change)
where TException : DbUpdateException
=> ConcurrencyTestAsync(
null, change, change);
@@ -128,21 +139,33 @@ protected virtual Task ConcurrencyTestAsync(
/// the database at the end of the process can be validated.
///
protected virtual async Task ConcurrencyTestAsync(
- Action seedAction,
- Action storeChange,
- Action clientChange)
+ Func seedAction,
+ Func storeChange,
+ Func clientChange)
where TException : DbUpdateException
{
using var outerContext = CreateContext();
await Fixture.TestStore.CleanAsync(outerContext);
- seedAction?.Invoke(outerContext);
+
+ if (seedAction != null)
+ {
+ await seedAction(outerContext);
+ }
+
await outerContext.SaveChangesAsync();
- clientChange?.Invoke(outerContext);
+ if (clientChange != null)
+ {
+ await clientChange(outerContext);
+ }
using (var innerContext = CreateContext())
{
- storeChange?.Invoke(innerContext);
+ if (storeChange != null)
+ {
+ await storeChange(innerContext);
+ }
+
await innerContext.SaveChangesAsync();
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs
index e70e4518e6d..d1c24275fa3 100644
--- a/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs
@@ -24,53 +24,53 @@ public override Task Can_filter_projection_with_captured_enum_variable(bool asyn
=> base.Can_filter_projection_with_captured_enum_variable(async);
[ConditionalFact(Skip = "Issue #17246 No Explicit Convert")]
- public override void Can_query_with_null_parameters_using_any_nullable_data_type()
+ public override Task Can_query_with_null_parameters_using_any_nullable_data_type()
=> base.Can_query_with_null_parameters_using_any_nullable_data_type();
[ConditionalFact(Skip = "Issue #16920")]
- public override void Can_insert_and_read_back_with_string_key()
+ public override Task Can_insert_and_read_back_with_string_key()
=> base.Can_insert_and_read_back_with_string_key();
[ConditionalFact(Skip = "Issue #17246 No Explicit Convert")]
- public override void Can_query_and_update_with_conversion_for_custom_type()
+ public override Task Can_query_and_update_with_conversion_for_custom_type()
=> base.Can_query_and_update_with_conversion_for_custom_type();
[ConditionalFact(Skip = "Issue #16920")]
- public override void Can_query_and_update_with_nullable_converter_on_primary_key()
+ public override Task Can_query_and_update_with_nullable_converter_on_primary_key()
=> base.Can_query_and_update_with_nullable_converter_on_primary_key();
[ConditionalFact(Skip = "Issue #16920")]
- public override void Can_insert_and_read_back_with_binary_key()
+ public override Task Can_insert_and_read_back_with_binary_key()
=> base.Can_insert_and_read_back_with_binary_key();
[ConditionalFact(Skip = "Issue #16920")]
- public override void Can_insert_and_read_back_with_case_insensitive_string_key()
+ public override Task Can_insert_and_read_back_with_case_insensitive_string_key()
=> base.Can_insert_and_read_back_with_case_insensitive_string_key();
[ConditionalFact(Skip = "Issue #17246 No Explicit Convert")]
- public override void Can_insert_and_query_struct_to_string_converter_for_pk()
+ public override Task Can_insert_and_query_struct_to_string_converter_for_pk()
=> base.Can_insert_and_query_struct_to_string_converter_for_pk();
[ConditionalFact(Skip = "Issue #17670")]
- public override void Can_read_back_mapped_enum_from_collection_first_or_default()
+ public override Task Can_read_back_mapped_enum_from_collection_first_or_default()
=> base.Can_read_back_mapped_enum_from_collection_first_or_default();
[ConditionalFact(Skip = "Issue #17246")]
- public override void Can_read_back_bool_mapped_as_int_through_navigation()
+ public override Task Can_read_back_bool_mapped_as_int_through_navigation()
=> base.Can_read_back_bool_mapped_as_int_through_navigation();
[ConditionalFact(Skip = "Issue #17246")]
- public override void Value_conversion_is_appropriately_used_for_join_condition()
+ public override Task Value_conversion_is_appropriately_used_for_join_condition()
=> base.Value_conversion_is_appropriately_used_for_join_condition();
[ConditionalFact(Skip = "Issue #17246")]
- public override void Value_conversion_is_appropriately_used_for_left_join_condition()
+ public override Task Value_conversion_is_appropriately_used_for_left_join_condition()
=> base.Value_conversion_is_appropriately_used_for_left_join_condition();
[ConditionalFact]
- public override void Where_bool_gets_converted_to_equality_when_value_conversion_is_used()
+ public override async Task Where_bool_gets_converted_to_equality_when_value_conversion_is_used()
{
- base.Where_bool_gets_converted_to_equality_when_value_conversion_is_used();
+ await base.Where_bool_gets_converted_to_equality_when_value_conversion_is_used();
AssertSql(
"""
@@ -81,9 +81,9 @@ FROM root c
}
[ConditionalFact]
- public override void Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used()
+ public override async Task Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used()
{
- base.Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used();
+ await base.Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used();
AssertSql(
"""
@@ -94,9 +94,9 @@ FROM root c
}
[ConditionalFact]
- public override void Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_EFProperty()
+ public override async Task Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_EFProperty()
{
- base.Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_EFProperty();
+ await base.Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_EFProperty();
AssertSql(
"""
@@ -107,9 +107,9 @@ FROM root c
}
[ConditionalFact]
- public override void Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_indexer()
+ public override async Task Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_indexer()
{
- base.Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_indexer();
+ await base.Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_indexer();
AssertSql(
"""
@@ -136,6 +136,9 @@ public override void GroupBy_converted_enum()
public override void Infer_type_mapping_from_in_subquery_to_item()
=> Assert.Throws(() => base.Infer_type_mapping_from_in_subquery_to_item());
+ public override Task Can_query_custom_type_not_mapped_by_default_equality(bool async)
+ => CosmosTestHelpers.Instance.NoSyncTest(async, a => base.Can_query_custom_type_not_mapped_by_default_equality(a));
+
private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
diff --git a/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs b/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs
index b745c1a85ec..bd9f333f820 100644
--- a/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs
@@ -25,7 +25,7 @@ public EmbeddedDocumentsTest(CosmosFixture fixture, ITestOutputHelper testOutput
[ConditionalFact(Skip = "Issue #17670")]
public virtual async Task Can_update_dependents()
{
- var options = Fixture.CreateOptions();
+ var options = await Fixture.CreateOptions();
Operator firstOperator;
Engine firstEngine;
using (var context = new EmbeddedTransportationContext(options))
@@ -53,11 +53,11 @@ public virtual async Task Can_update_dependents()
[ConditionalFact]
public virtual async Task Can_update_owner_with_dependents()
{
- var options = Fixture.CreateOptions();
+ var options = await Fixture.CreateOptions();
Operator firstOperator;
using (var context = new EmbeddedTransportationContext(options))
{
- firstOperator = context.Set().OrderBy(o => o.Name).First().Operator;
+ firstOperator = (await context.Set().OrderBy(o => o.Name).FirstAsync()).Operator;
firstOperator.Name += "1";
await context.SaveChangesAsync();
@@ -73,7 +73,7 @@ public virtual async Task Can_update_owner_with_dependents()
[ConditionalFact]
public virtual async Task Can_attach_owner_with_dependents()
{
- var options = Fixture.CreateOptions();
+ var options = await Fixture.CreateOptions();
Vehicle firstVehicle;
using (var context = new EmbeddedTransportationContext(options))
{
@@ -104,15 +104,16 @@ public virtual async Task Can_attach_owner_with_dependents()
[InlineData(true)]
public virtual async Task Can_manipulate_embedded_collections(bool useIds)
{
- var options = Fixture.CreateOptions(seed: false);
- var swappedOptions = Fixture.CreateOptions(modelBuilder => modelBuilder.Entity(
+ var options = await Fixture.CreateOptions(seed: false);
+ var swappedOptions = await Fixture.CreateOptions(
+ modelBuilder => modelBuilder.Entity(
eb => eb.OwnsMany(
v => v.Addresses, b =>
{
b.OwnsMany(a => a.Notes).ToJsonProperty("IdNotes");
b.OwnsMany(a => a.IdNotes).ToJsonProperty("Notes");
})),
- seed: false);
+ seed: false);
Address existingAddress1Person2;
Address existingAddress1Person3;
@@ -318,6 +319,7 @@ async Task AssertState(EmbeddedTransportationContext context, bool useIds)
Assert.Equal(1, notes.First().Id);
Assert.Equal(2, notes.Last().Id);
}
+
Assert.Equal("First note", notes.First().Content);
Assert.Equal("Second note", notes.Last().Content);
}
@@ -390,38 +392,34 @@ async Task AssertState(EmbeddedTransportationContext context, bool useIds)
[ConditionalFact]
public virtual async Task Old_still_works()
{
- var options = Fixture.CreateOptions(seed: false);
- var swappedOptions = Fixture.CreateOptions(modelBuilder => modelBuilder.Entity(
+ var options = await Fixture.CreateOptions(seed: false);
+ var swappedOptions = await Fixture.CreateOptions(
+ modelBuilder => modelBuilder.Entity(
eb => eb.OwnsMany(
v => v.Addresses, b =>
{
b.OwnsMany(a => a.Notes).ToJsonProperty("IdNotes");
b.OwnsMany(a => a.IdNotes).ToJsonProperty("Notes");
})),
- seed: false);
+ seed: false);
using (var context = new EmbeddedTransportationContext(options))
{
- await context.AddAsync(new Person
- {
- Id = 1,
- Addresses = new List
+ await context.AddAsync(
+ new Person
{
- new()
+ Id = 1,
+ Addresses = new List
{
- Street = "Second",
- City = "Village",
- Notes = new List
- {
- new() { Content = "First note" }
- },
- IdNotes = new List
+ new()
{
- new() { Id = 3, Content = "Second note" }
+ Street = "Second",
+ City = "Village",
+ Notes = new List { new() { Content = "First note" } },
+ IdNotes = new List { new() { Id = 3, Content = "Second note" } }
}
}
- }
- });
+ });
await context.SaveChangesAsync();
}
@@ -459,7 +457,7 @@ public record struct CosmosPage(List Results, string ContinuationToken);
[ConditionalFact]
public virtual async Task Properties_on_owned_types_can_be_client_generated()
{
- var options = Fixture.CreateOptions(seed: false);
+ var options = await Fixture.CreateOptions(seed: false);
using (var context = new EmbeddedTransportationContext(options))
{
@@ -483,7 +481,7 @@ public virtual async Task Properties_on_owned_types_can_be_client_generated()
[ConditionalFact]
public virtual async Task Can_use_non_int_keys_for_embedded_entities()
{
- var options = Fixture.CreateOptions(
+ var options = await Fixture.CreateOptions(
modelBuilder =>
{
modelBuilder.Entity(
@@ -529,10 +527,10 @@ public virtual async Task Can_use_non_int_keys_for_embedded_entities()
[ConditionalFact]
public virtual async Task Can_query_and_modify_nested_embedded_types()
{
- var options = Fixture.CreateOptions();
+ var options = await Fixture.CreateOptions();
using (var context = new EmbeddedTransportationContext(options))
{
- var missile = context.Set().First(v => v.Name == "AIM-9M Sidewinder");
+ var missile = await context.Set().FirstAsync(v => v.Name == "AIM-9M Sidewinder");
Assert.Equal("Heat-seeking", missile.Operator.Details.Type);
@@ -543,7 +541,7 @@ public virtual async Task Can_query_and_modify_nested_embedded_types()
using (var context = new EmbeddedTransportationContext(options))
{
- var missile = context.Set().First(v => v.Name == "AIM-9M Sidewinder");
+ var missile = await context.Set().FirstAsync(v => v.Name == "AIM-9M Sidewinder");
Assert.Equal("IR", missile.Operator.Details.Type);
}
@@ -552,7 +550,7 @@ public virtual async Task Can_query_and_modify_nested_embedded_types()
[ConditionalFact]
public virtual async Task Can_query_just_embedded_reference()
{
- var options = Fixture.CreateOptions();
+ var options = await Fixture.CreateOptions();
using var context = new EmbeddedTransportationContext(options);
var firstOperator = await context.Set().OrderBy(o => o.Name).Select(v => v.Operator)
.AsNoTracking().FirstAsync();
@@ -564,7 +562,7 @@ public virtual async Task Can_query_just_embedded_reference()
[ConditionalFact]
public virtual async Task Can_query_just_embedded_collection()
{
- var options = Fixture.CreateOptions(seed: false);
+ var options = await Fixture.CreateOptions(seed: false);
using (var context = new EmbeddedTransportationContext(options))
{
@@ -592,7 +590,7 @@ await context.AddAsync(
[ConditionalFact]
public virtual async Task Inserting_dependent_without_principal_throws()
{
- var options = Fixture.CreateOptions(seed: false);
+ var options = await Fixture.CreateOptions(seed: false);
using var context = new EmbeddedTransportationContext(options);
await context.AddAsync(
new LicensedOperator
@@ -611,7 +609,7 @@ await context.AddAsync(
[ConditionalFact]
public virtual async Task Can_change_nested_instance_non_derived()
{
- var options = Fixture.CreateOptions();
+ var options = await Fixture.CreateOptions();
using (var context = new EmbeddedTransportationContext(options))
{
var bike = await context.Vehicles.SingleAsync(v => v.Name == "Trek Pro Fit Madone 6 Series");
@@ -636,7 +634,7 @@ public virtual async Task Can_change_nested_instance_non_derived()
[ConditionalFact]
public virtual async Task Can_change_principal_instance_non_derived()
{
- var options = Fixture.CreateOptions();
+ var options = await Fixture.CreateOptions();
using (var context = new EmbeddedTransportationContext(options))
{
var bike = await context.Vehicles.SingleAsync(v => v.Name == "Trek Pro Fit Madone 6 Series");
@@ -685,18 +683,18 @@ protected override ITestStoreFactory TestStoreFactory
public virtual CosmosTestStore TestStore { get; }
- public EmbeddedTransportationContextOptions CreateOptions(
+ public async Task CreateOptions(
Action onModelCreating = null,
bool seed = true)
{
var options = CreateOptions(TestStore);
var embeddedOptions = new EmbeddedTransportationContextOptions(options, onModelCreating);
- TestStore.Initialize(
- ServiceProvider, () => new EmbeddedTransportationContext(embeddedOptions), c =>
+ await TestStore.InitializeAsync(
+ ServiceProvider, () => new EmbeddedTransportationContext(embeddedOptions), async c =>
{
if (seed)
{
- ((TransportationContext)c).Seed();
+ await ((TransportationContext)c).SeedAsync();
}
});
@@ -710,7 +708,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
protected override object GetAdditionalModelCacheKey(DbContext context)
{
var options = ((EmbeddedTransportationContext)context).Options;
- return options.OnModelCreating == null
+ return options.OnModelCreating == null
? null
: options;
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs
index f818a133d33..8d052c48581 100644
--- a/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs
@@ -12,41 +12,44 @@ namespace Microsoft.EntityFrameworkCore;
#nullable disable
-public class EndToEndCosmosTest(EndToEndCosmosTest.CosmosFixture fixture) : IClassFixture
+public class EndToEndCosmosTest : NonSharedModelTestBase
{
- private const string DatabaseName = "CosmosEndToEndTest";
-
- protected CosmosFixture Fixture { get; } = fixture;
-
[ConditionalFact]
- public void Can_add_update_delete_end_to_end()
+ public async Task Can_add_update_delete_end_to_end()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
+ ListLoggerFactory.Clear();
context.Database.EnsureCreated();
context.Add(customer);
context.SaveChanges();
- var logEntry = TestSqlLoggerFactory.Log.Single();
+ var logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedCreateItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("CreateItem", logEntry.Message);
+
+ Assert.Equal(3, ListLoggerFactory.Log.Count(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
- TestSqlLoggerFactory.Clear();
+ ListLoggerFactory.Clear();
var customerFromStore = context.Set().Single();
- var logEntry = TestSqlLoggerFactory.Log.Last();
+ var logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedReadNext);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("ReadNext", logEntry.Message);
- TestSqlLoggerFactory.Clear();
+ Assert.Single(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
+ ListLoggerFactory.Clear();
Assert.Equal(42, customerFromStore.Id);
Assert.Equal("Theon", customerFromStore.Name);
@@ -55,20 +58,23 @@ public void Can_add_update_delete_end_to_end()
context.SaveChanges();
- logEntry = TestSqlLoggerFactory.Log.Single();
+ logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedReplaceItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("ReplaceItem", logEntry.Message);
+
+ Assert.Single(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
- TestSqlLoggerFactory.Clear();
+ ListLoggerFactory.Clear();
var customerFromStore = context.Find(42);
- var logEntry = TestSqlLoggerFactory.Log.Last();
+ var logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedReadItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("ReadItem", logEntry.Message);
- TestSqlLoggerFactory.Clear();
+ Assert.Single(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
+ ListLoggerFactory.Clear();
Assert.Equal(42, customerFromStore.Id);
Assert.Equal("Theon Greyjoy", customerFromStore.Name);
@@ -77,25 +83,33 @@ public void Can_add_update_delete_end_to_end()
context.SaveChanges();
- logEntry = TestSqlLoggerFactory.Log.Single();
+ logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedDeleteItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("DeleteItem", logEntry.Message);
+
+ Assert.Single(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
+ ListLoggerFactory.Clear();
Assert.Empty(context.Set().ToList());
+
+ Assert.Single(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
[ConditionalFact]
public async Task Can_add_update_delete_end_to_end_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -103,19 +117,22 @@ public async Task Can_add_update_delete_end_to_end_async()
await context.SaveChangesAsync();
- var logEntry = TestSqlLoggerFactory.Log.Single();
+ var logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedCreateItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("CreateItem", logEntry.Message);
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
- var logEntry = TestSqlLoggerFactory.Log.Last();
+ var logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedReadNext);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("ReadNext", logEntry.Message);
- TestSqlLoggerFactory.Clear();
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
+ ListLoggerFactory.Clear();
Assert.Equal(42, customerFromStore.Id);
Assert.Equal("Theon", customerFromStore.Name);
@@ -124,19 +141,21 @@ public async Task Can_add_update_delete_end_to_end_async()
await context.SaveChangesAsync();
- logEntry = TestSqlLoggerFactory.Log.Single();
+ logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedReplaceItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("ReplaceItem", logEntry.Message);
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.FindAsync(42);
- var logEntry = TestSqlLoggerFactory.Log.Last();
+ var logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedReadItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("ReadItem", logEntry.Message);
- TestSqlLoggerFactory.Clear();
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
+ ListLoggerFactory.Clear();
Assert.Equal(42, customerFromStore.Id);
Assert.Equal("Theon Greyjoy", customerFromStore.Name);
@@ -145,25 +164,30 @@ public async Task Can_add_update_delete_end_to_end_async()
await context.SaveChangesAsync();
- logEntry = TestSqlLoggerFactory.Log.Single();
+ logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedDeleteItem);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("DeleteItem", logEntry.Message);
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
[ConditionalFact]
public async Task Can_add_update_delete_detached_entity_end_to_end_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
string storeId = null;
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -174,19 +198,23 @@ public async Task Can_add_update_delete_detached_entity_end_to_end_async()
await context.AddAsync(customer);
storeId = entry.Property(StoreKeyConvention.DefaultIdPropertyName).CurrentValue;
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
Assert.Equal("Customer|42", storeId);
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
Assert.Equal(42, customerFromStore.Id);
Assert.Equal("Theon", customerFromStore.Name);
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
customer.Name = "Theon Greyjoy";
@@ -196,39 +224,49 @@ public async Task Can_add_update_delete_detached_entity_end_to_end_async()
entry.State = EntityState.Modified;
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
- var customerFromStore = context.Set().Single();
+ var customerFromStore = await context.Set().SingleAsync();
Assert.Equal(42, customerFromStore.Id);
Assert.Equal("Theon Greyjoy", customerFromStore.Name);
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var entry = context.Entry(customer);
entry.Property(StoreKeyConvention.DefaultIdPropertyName).CurrentValue = storeId;
entry.State = EntityState.Deleted;
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
[ConditionalFact]
- public void Can_add_update_untracked_properties()
+ public async Task Can_add_update_untracked_properties()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
context.Database.EnsureCreated();
@@ -243,9 +281,11 @@ public void Can_add_update_untracked_properties()
context.Remove(customer);
context.SaveChanges();
+
+ Assert.Equal(4, ListLoggerFactory.Log.Count(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(context.Set().ToList());
@@ -263,9 +303,11 @@ public void Can_add_update_untracked_properties()
document["key2"] = "value2";
entry.State = EntityState.Modified;
context.SaveChanges();
+
+ Assert.Equal(7, ListLoggerFactory.Log.Count(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Single();
@@ -281,9 +323,11 @@ public void Can_add_update_untracked_properties()
customerFromStore.Name = "Theon Greyjoy";
context.SaveChanges();
+
+ Assert.Equal(9, ListLoggerFactory.Log.Count(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Single();
@@ -297,22 +341,28 @@ public void Can_add_update_untracked_properties()
context.Remove(customerFromStore);
context.SaveChanges();
+
+ Assert.Equal(11, ListLoggerFactory.Log.Count(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(context.Set().ToList());
+ Assert.Equal(12, ListLoggerFactory.Log.Count(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
[ConditionalFact]
public async Task Can_add_update_untracked_properties_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -327,9 +377,11 @@ public async Task Can_add_update_untracked_properties_async()
context.Remove(customer);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
@@ -347,9 +399,11 @@ public async Task Can_add_update_untracked_properties_async()
document["key2"] = "value2";
entry.State = EntityState.Modified;
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
@@ -365,9 +419,11 @@ public async Task Can_add_update_untracked_properties_async()
customerFromStore.Name = "Theon Greyjoy";
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
@@ -381,18 +437,30 @@ public async Task Can_add_update_untracked_properties_async()
context.Remove(customerFromStore);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
[ConditionalFact]
public async Task Can_add_update_delete_end_to_end_with_Guid_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(
+ b =>
+ {
+ b.Property(c => c.Id).ToJsonProperty("id");
+ b.Property(c => c.PartitionKey).HasConversion().ToJsonProperty("pk");
+ b.HasPartitionKey(c => c.PartitionKey);
+ }),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new CustomerGuid
{
@@ -401,16 +469,18 @@ public async Task Can_add_update_delete_end_to_end_with_Guid_async()
PartitionKey = 42
};
- using (var context = new CustomerContextGuid(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
await context.AddAsync(customer);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContextGuid(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
@@ -420,9 +490,11 @@ public async Task Can_add_update_delete_end_to_end_with_Guid_async()
customerFromStore.Name = "Theon Greyjoy";
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContextGuid(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
@@ -432,18 +504,31 @@ public async Task Can_add_update_delete_end_to_end_with_Guid_async()
context.Remove(customerFromStore);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContextGuid(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
[ConditionalFact]
public async Task Can_add_update_delete_end_to_end_with_DateTime_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(
+ b =>
+ {
+ b.Property(c => c.Id);
+ b.Property(c => c.PartitionKey).HasConversion();
+ b.HasPartitionKey(c => c.PartitionKey);
+ b.HasKey(c => new { c.Id, c.Name });
+ }),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new CustomerDateTime
{
@@ -452,7 +537,7 @@ public async Task Can_add_update_delete_end_to_end_with_DateTime_async()
PartitionKey = 42
};
- using (var context = new CustomerContextDateTime(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -461,9 +546,11 @@ public async Task Can_add_update_delete_end_to_end_with_DateTime_async()
Assert.Equal("CustomerDateTime|0001-01-01T00:00:00.0000000|Theon^2F^5C^23^5C^5C^3F", entry.CurrentValues["__id"]);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContextDateTime(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
@@ -473,9 +560,11 @@ public async Task Can_add_update_delete_end_to_end_with_DateTime_async()
customerFromStore.Value = 23;
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContextDateTime(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
@@ -485,11 +574,14 @@ public async Task Can_add_update_delete_end_to_end_with_DateTime_async()
context.Remove(customerFromStore);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContextDateTime(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
@@ -528,61 +620,35 @@ private class CustomerNoPartitionKey
public string Name { get; set; }
}
- private class CustomerContext(DbContextOptions dbContextOptions) : DbContext(dbContextOptions)
- {
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- => modelBuilder.Entity();
- }
-
- private class CustomerContextGuid(DbContextOptions dbContextOptions) : DbContext(dbContextOptions)
- {
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- => modelBuilder.Entity(
- cb =>
- {
- cb.Property(c => c.Id).ToJsonProperty("id");
- cb.Property(c => c.PartitionKey).HasConversion().ToJsonProperty("pk");
- cb.HasPartitionKey(c => c.PartitionKey);
- });
- }
-
- private class CustomerContextDateTime(DbContextOptions dbContextOptions) : DbContext(dbContextOptions)
- {
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- => modelBuilder.Entity(
- cb =>
- {
- cb.Property(c => c.Id);
- cb.Property(c => c.PartitionKey).HasConversion();
- cb.HasPartitionKey(c => c.PartitionKey);
- cb.HasKey(c => new { c.Id, c.Name });
- });
- }
-
[ConditionalFact]
public async Task Can_add_update_delete_with_dateTime_string_end_to_end_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ b => b.Entity(),
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "2021-08-23T06:23:40+00:00" };
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
await context.AddAsync(customer);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
- var logEntry = TestSqlLoggerFactory.Log.Last();
+ var logEntry = ListLoggerFactory.Log.Single(e => e.Id == CosmosEventId.ExecutedReadNext);
Assert.Equal(LogLevel.Information, logEntry.Level);
Assert.Contains("ReadNext", logEntry.Message);
- TestSqlLoggerFactory.Clear();
+ ListLoggerFactory.Clear();
Assert.Equal(42, customerFromStore.Id);
Assert.Equal("2021-08-23T06:23:40+00:00", customerFromStore.Name);
@@ -590,9 +656,11 @@ public async Task Can_add_update_delete_with_dateTime_string_end_to_end_async()
customerFromStore.Name = "2021-08-23T06:23:40+02:00";
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.FindAsync(42);
@@ -602,19 +670,26 @@ public async Task Can_add_update_delete_with_dateTime_string_end_to_end_async()
context.Remove(customerFromStore);
await context.SaveChangesAsync();
+
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
- using (var context = new CustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
+ Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported));
}
}
+
[ConditionalFact]
public async Task Entities_with_null_PK_can_be_added_with_normal_use_of_DbContext_methods_and_have_id_shadow_value_and_PK_created()
{
- await using var testDatabase = CosmosTestStore.Create("IdentifierShadowValuePresenceTest");
- using var context = new IdentifierShadowValuePresenceTestContext(testDatabase);
+ var contextFactory = await InitializeAsync(
+ usePooling: false,
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+ var context = contextFactory.CreateContext();
var item = new GItem();
Assert.Null(item.Id);
@@ -634,8 +709,12 @@ public async Task Entities_with_null_PK_can_be_added_with_normal_use_of_DbContex
public async Task
Entities_can_be_tracked_with_normal_use_of_DbContext_methods_and_have_correct_resultant_state_and_id_shadow_value()
{
- await using var testDatabase = CosmosTestStore.Create("IdentifierShadowValuePresenceTest");
- using var context = new IdentifierShadowValuePresenceTestContext(testDatabase);
+ var contextFactory = await InitializeAsync(
+ usePooling: false,
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
+ var context = contextFactory.CreateContext();
var item = new Item { Id = 1337 };
var entry = context.Attach(item);
@@ -656,26 +735,9 @@ public async Task
Assert.Equal(EntityState.Deleted, entry.State);
}
- protected class IdentifierShadowValuePresenceTestContext(CosmosTestStore testStore) : DbContext
+ protected class IdentifierShadowValuePresenceTestContext(DbContextOptions dbContextOptions) : DbContext(dbContextOptions)
{
- private readonly string _connectionUri = testStore.ConnectionUri;
- private readonly string _authToken = testStore.AuthToken;
- private readonly string _name = testStore.Name;
-
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- => optionsBuilder
- .UseCosmos(
- _connectionUri,
- _authToken,
- _name,
- b => b.ApplyConfiguration());
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- }
-
public DbSet GItems { get; set; }
-
public DbSet- Items { get; set; }
}
@@ -875,7 +937,10 @@ private async Task Can_add_update_delete_with_collection(
Action onModelBuilder = null)
where TCollection : class
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync>(
+ shouldLogCategory: _ => true,
+ onModelCreating: onModelBuilder,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new CustomerWithCollection
{
@@ -884,7 +949,7 @@ private async Task Can_add_update_delete_with_collection(
Collection = initialValue
};
- using (var context = new CollectionCustomerContext(options, onModelBuilder))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -893,7 +958,7 @@ private async Task Can_add_update_delete_with_collection(
await context.SaveChangesAsync();
}
- using (var context = new CollectionCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Customers.SingleAsync();
@@ -905,7 +970,7 @@ private async Task Can_add_update_delete_with_collection(
await context.SaveChangesAsync();
}
- using (var context = new CollectionCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Customers.SingleAsync();
@@ -917,7 +982,7 @@ private async Task Can_add_update_delete_with_collection(
await context.SaveChangesAsync();
}
- using (var context = new CollectionCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Customers.SingleAsync();
@@ -933,21 +998,23 @@ private class CustomerWithCollection
public TCollection Collection { get; set; }
}
- private class CollectionCustomerContext(DbContextOptions dbContextOptions, Action onModelBuilder = null) : DbContext(dbContextOptions)
+ private class CollectionCustomerContext(DbContextOptions dbContextOptions, Action onModelBuilder = null)
+ : DbContext(dbContextOptions)
{
- private readonly Action _onModelBuilder = onModelBuilder;
-
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public DbSet> Customers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
- => _onModelBuilder?.Invoke(modelBuilder);
+ => onModelBuilder?.Invoke(modelBuilder);
}
[ConditionalFact]
public async Task Can_read_with_find_with_resource_id_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
const int pk1 = 1;
const int pk2 = 2;
@@ -958,7 +1025,7 @@ public async Task Can_read_with_find_with_resource_id_async()
PartitionKey = pk1
};
- await using (var context = new PartitionKeyContextWithResourceId(options))
+ await using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -978,7 +1045,7 @@ await context.AddAsync(
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextWithResourceId(options))
+ await using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set()
.FindAsync(pk1, "42");
@@ -993,7 +1060,7 @@ await context.AddAsync(
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextWithResourceId(options))
+ await using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set()
.WithPartitionKey(partitionKey: pk1.ToString())
@@ -1006,9 +1073,12 @@ await context.AddAsync(
}
[ConditionalFact]
- public void Can_read_with_find_with_resource_id()
+ public async Task Can_read_with_find_with_resource_id()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
const int pk1 = 1;
const int pk2 = 2;
@@ -1019,7 +1089,7 @@ public void Can_read_with_find_with_resource_id()
PartitionKey = pk1
};
- using (var context = new PartitionKeyContextWithResourceId(options))
+ using (var context = contextFactory.CreateContext())
{
context.Database.EnsureCreated();
@@ -1035,7 +1105,7 @@ public void Can_read_with_find_with_resource_id()
context.SaveChanges();
}
- using (var context = new PartitionKeyContextWithResourceId(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set()
.Find(pk1, "42");
@@ -1050,7 +1120,7 @@ public void Can_read_with_find_with_resource_id()
context.SaveChanges();
}
- using (var context = new PartitionKeyContextWithResourceId(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set()
.WithPartitionKey(partitionKey: pk1.ToString())
@@ -1063,10 +1133,13 @@ public void Can_read_with_find_with_resource_id()
}
[ConditionalFact]
- public void Find_with_empty_resource_id_throws()
+ public async Task Find_with_empty_resource_id_throws()
{
- var options = Fixture.CreateOptions();
- using (var context = new PartitionKeyContextWithResourceId(options))
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
+ using (var context = contextFactory.CreateContext())
{
context.Database.EnsureCreated();
@@ -1079,7 +1152,10 @@ public void Find_with_empty_resource_id_throws()
[ConditionalFact]
public async Task Can_read_with_find_with_partition_key_and_value_generator_async()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
const int pk1 = 1;
const int pk2 = 2;
@@ -1090,7 +1166,7 @@ public async Task Can_read_with_find_with_partition_key_and_value_generator_asyn
PartitionKey = pk1
};
- await using (var context = new PartitionKeyContextCustomValueGenerator(options))
+ await using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1106,7 +1182,7 @@ await context.AddAsync(
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextCustomValueGenerator(options))
+ await using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set()
.FindAsync(pk1, 42);
@@ -1120,7 +1196,7 @@ await context.AddAsync(
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextCustomValueGenerator(options))
+ await using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set()
.WithPartitionKey(partitionKey: pk1.ToString())
@@ -1133,9 +1209,12 @@ await context.AddAsync(
}
[ConditionalFact]
- public void Can_read_with_find_with_partition_key_and_value_generator()
+ public async Task Can_read_with_find_with_partition_key_and_value_generator()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
const int pk1 = 1;
const int pk2 = 2;
@@ -1146,7 +1225,7 @@ public void Can_read_with_find_with_partition_key_and_value_generator()
PartitionKey = pk1
};
- using (var context = new PartitionKeyContextCustomValueGenerator(options))
+ using (var context = contextFactory.CreateContext())
{
context.Database.EnsureCreated();
@@ -1162,7 +1241,7 @@ public void Can_read_with_find_with_partition_key_and_value_generator()
context.SaveChanges();
}
- using (var context = new PartitionKeyContextCustomValueGenerator(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set()
.Find(pk1, 42);
@@ -1177,7 +1256,7 @@ public void Can_read_with_find_with_partition_key_and_value_generator()
context.SaveChanges();
}
- using (var context = new PartitionKeyContextCustomValueGenerator(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set()
.WithPartitionKey(partitionKey: pk1.ToString())
@@ -1190,9 +1269,12 @@ public void Can_read_with_find_with_partition_key_and_value_generator()
}
[ConditionalFact]
- public void Can_read_with_find_with_partition_key_without_value_generator()
+ public async Task Can_read_with_find_with_partition_key_without_value_generator()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
const int pk1 = 1;
var customer = new Customer
@@ -1202,7 +1284,7 @@ public void Can_read_with_find_with_partition_key_without_value_generator()
PartitionKey = pk1
};
- using (var context = new PartitionKeyContextNoValueGenerator(options))
+ using (var context = contextFactory.CreateContext())
{
context.Database.EnsureCreated();
@@ -1213,7 +1295,7 @@ public void Can_read_with_find_with_partition_key_without_value_generator()
context.SaveChanges();
}
- using (var context = new PartitionKeyContextNoValueGenerator(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set()
.Find(pk1, 42);
@@ -1237,7 +1319,7 @@ OFFSET 0 LIMIT 1
context.SaveChanges();
}
- using (var context = new PartitionKeyContextNoValueGenerator(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set()
.WithPartitionKey(partitionKey: pk1.ToString())
@@ -1252,7 +1334,9 @@ OFFSET 0 LIMIT 1
[ConditionalFact]
public async Task Can_read_with_find_with_partition_key_not_part_of_primary_key()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer
{
@@ -1261,7 +1345,7 @@ public async Task Can_read_with_find_with_partition_key_not_part_of_primary_key(
PartitionKey = 1
};
- await using (var context = new PartitionKeyContextNonPrimaryKey(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1270,7 +1354,7 @@ public async Task Can_read_with_find_with_partition_key_not_part_of_primary_key(
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextNonPrimaryKey(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Find(42);
@@ -1283,11 +1367,13 @@ public async Task Can_read_with_find_with_partition_key_not_part_of_primary_key(
[ConditionalFact]
public async Task Can_read_with_find_without_partition_key()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new CustomerNoPartitionKey { Id = 42, Name = "Theon" };
- await using (var context = new PartitionKeyContextEntityWithNoPartitionKey(options))
+ await using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1296,7 +1382,7 @@ public async Task Can_read_with_find_without_partition_key()
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextEntityWithNoPartitionKey(options))
+ await using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Find(42);
@@ -1309,11 +1395,13 @@ public async Task Can_read_with_find_without_partition_key()
[ConditionalFact]
public async Task Can_read_with_find_with_PK_partition_key()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new CustomerGuid { Id = Guid.NewGuid(), Name = "Theon" };
- await using (var context = new PartitionKeyContextPrimaryKey(options))
+ await using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1322,7 +1410,7 @@ public async Task Can_read_with_find_with_PK_partition_key()
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextPrimaryKey(options))
+ await using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Find(customer.Id);
@@ -1335,11 +1423,13 @@ public async Task Can_read_with_find_with_PK_partition_key()
[ConditionalFact]
public async Task Can_read_with_find_with_PK_resource_id()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new CustomerWithResourceId { id = "42", Name = "Theon" };
- await using (var context = new PartitionKeyContextWithPrimaryKeyResourceId(options))
+ await using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1348,7 +1438,7 @@ public async Task Can_read_with_find_with_PK_resource_id()
await context.SaveChangesAsync();
}
- await using (var context = new PartitionKeyContextWithPrimaryKeyResourceId(options))
+ await using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Find("42");
@@ -1461,11 +1551,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
[ConditionalFact]
public async Task Can_use_detached_entities_without_discriminators()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new NoDiscriminatorCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1474,7 +1566,7 @@ public async Task Can_use_detached_entities_without_discriminators()
await context.SaveChangesAsync();
}
- using (var context = new NoDiscriminatorCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
(await context.AddAsync(customer)).State = EntityState.Modified;
@@ -1483,7 +1575,7 @@ public async Task Can_use_detached_entities_without_discriminators()
await context.SaveChangesAsync();
}
- using (var context = new NoDiscriminatorCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().AsNoTracking().Single();
@@ -1495,26 +1587,28 @@ public async Task Can_use_detached_entities_without_discriminators()
await context.SaveChangesAsync();
}
- using (var context = new NoDiscriminatorCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(await context.Set().ToListAsync());
}
}
- private class NoDiscriminatorCustomerContext(DbContextOptions dbContextOptions) : CustomerContext(dbContextOptions)
+ private class NoDiscriminatorCustomerContext(DbContextOptions dbContextOptions) : DbContext(dbContextOptions)
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity().HasNoDiscriminator();
}
[ConditionalFact]
- public void Can_update_unmapped_properties()
+ public async Task Can_update_unmapped_properties()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new ExtraCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
context.Database.EnsureCreated();
@@ -1524,7 +1618,7 @@ public void Can_update_unmapped_properties()
context.SaveChanges();
}
- using (var context = new ExtraCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Single();
@@ -1536,7 +1630,7 @@ public void Can_update_unmapped_properties()
context.SaveChanges();
}
- using (var context = new ExtraCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = context.Set().Single();
@@ -1554,29 +1648,28 @@ public void Can_update_unmapped_properties()
context.SaveChanges();
}
- using (var context = new ExtraCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(context.Set().ToList());
}
}
- private class ExtraCustomerContext(DbContextOptions dbContextOptions) : CustomerContext(dbContextOptions)
+ private class ExtraCustomerContext(DbContextOptions dbContextOptions) : DbContext(dbContextOptions)
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.HasDefaultContainer(nameof(CustomerContext));
- modelBuilder.Entity().Property("EMail").ToJsonProperty("e-mail");
- }
+ => modelBuilder.Entity().Property("EMail").ToJsonProperty("e-mail");
}
[ConditionalFact]
public async Task Can_use_non_persisted_properties()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new UnmappedCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1586,7 +1679,7 @@ public async Task Can_use_non_persisted_properties()
Assert.Equal("Theon", customer.Name);
}
- using (var context = new UnmappedCustomerContext(options))
+ using (var context = contextFactory.CreateContext())
{
var customerFromStore = await context.Set().SingleAsync();
@@ -1599,7 +1692,7 @@ public async Task Can_use_non_persisted_properties()
}
}
- private class UnmappedCustomerContext(DbContextOptions dbContextOptions) : CustomerContext(dbContextOptions)
+ private class UnmappedCustomerContext(DbContextOptions dbContextOptions) : DbContext(dbContextOptions)
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity().Property(c => c.Name).ToJsonProperty("");
@@ -1608,11 +1701,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
[ConditionalFact]
public async Task Add_update_delete_query_throws_if_no_container()
{
- await using var testDatabase = CosmosTestStore.CreateInitialized(DatabaseName + "Empty");
- var options = Fixture.CreateOptions(testDatabase);
+ await using var testDatabase = await CosmosTestStore.CreateInitializedAsync("EndToEndEmpty");
+
+ var options = new DbContextOptionsBuilder()
+ .UseCosmos(testDatabase.ConnectionString, "EndToEndEmpty")
+ .Options;
var customer = new Customer { Id = 42, Name = "Theon" };
- using (var context = new CustomerContext(options))
+ using (var context = new EndToEndEmptyContext(options))
{
await context.AddAsync(customer);
@@ -1621,7 +1717,7 @@ public async Task Add_update_delete_query_throws_if_no_container()
(await Assert.ThrowsAsync(() => context.SaveChangesAsync())).InnerException!.Message);
}
- using (var context = new CustomerContext(options))
+ using (var context = new EndToEndEmptyContext(options))
{
(await context.AddAsync(customer)).State = EntityState.Modified;
@@ -1630,7 +1726,7 @@ public async Task Add_update_delete_query_throws_if_no_container()
(await Assert.ThrowsAsync(() => context.SaveChangesAsync())).InnerException!.Message);
}
- using (var context = new CustomerContext(options))
+ using (var context = new EndToEndEmptyContext(options))
{
(await context.AddAsync(customer)).State = EntityState.Deleted;
@@ -1639,7 +1735,7 @@ public async Task Add_update_delete_query_throws_if_no_container()
(await Assert.ThrowsAsync(() => context.SaveChangesAsync())).InnerException!.Message);
}
- using (var context = new CustomerContext(options))
+ using (var context = new EndToEndEmptyContext(options))
{
Assert.StartsWith(
"Response status code does not indicate success: NotFound (404); Substatus: 0",
@@ -1647,12 +1743,21 @@ public async Task Add_update_delete_query_throws_if_no_container()
}
}
+ private class EndToEndEmptyContext(DbContextOptions options) : DbContext(options)
+ {
+ public DbSet Customers
+ => Set();
+ }
+
[ConditionalFact]
public async Task Using_a_conflicting_incompatible_id_throws()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
+ using var context = contextFactory.CreateContext();
- using var context = new ConflictingIncompatibleIdContext(options);
await Assert.ThrowsAnyAsync(
async () =>
{
@@ -1680,11 +1785,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
[ConditionalFact]
public async Task Can_add_update_delete_end_to_end_with_conflicting_id()
{
- var options = Fixture.CreateOptions();
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
var entity = new ConflictingId { id = "42", Name = "Theon" };
- using (var context = new ConflictingIdContext(options))
+ using (var context = contextFactory.CreateContext())
{
await context.Database.EnsureCreatedAsync();
@@ -1693,7 +1800,7 @@ public async Task Can_add_update_delete_end_to_end_with_conflicting_id()
await context.SaveChangesAsync();
}
- using (var context = new ConflictingIdContext(options))
+ using (var context = contextFactory.CreateContext())
{
var entityFromStore = context.Set().Single();
@@ -1701,7 +1808,7 @@ public async Task Can_add_update_delete_end_to_end_with_conflicting_id()
Assert.Equal("Theon", entityFromStore.Name);
}
- using (var context = new ConflictingIdContext(options))
+ using (var context = contextFactory.CreateContext())
{
entity.Name = "Theon Greyjoy";
@@ -1710,7 +1817,7 @@ public async Task Can_add_update_delete_end_to_end_with_conflicting_id()
await context.SaveChangesAsync();
}
- using (var context = new ConflictingIdContext(options))
+ using (var context = contextFactory.CreateContext())
{
var entityFromStore = context.Set().Single();
@@ -1718,14 +1825,14 @@ public async Task Can_add_update_delete_end_to_end_with_conflicting_id()
Assert.Equal("Theon Greyjoy", entityFromStore.Name);
}
- using (var context = new ConflictingIdContext(options))
+ using (var context = contextFactory.CreateContext())
{
context.Remove(entity);
await context.SaveChangesAsync();
}
- using (var context = new ConflictingIdContext(options))
+ using (var context = contextFactory.CreateContext())
{
Assert.Empty(context.Set().ToList());
}
@@ -1748,7 +1855,24 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
[InlineData(false)]
public async Task Can_have_non_string_property_named_Discriminator(bool useDiscriminator)
{
- using var context = new NonStringDiscriminatorContext(Fixture.CreateOptions(), useDiscriminator);
+ var contextFactory = await InitializeAsync(
+ shouldLogCategory: _ => true,
+ onModelCreating: b =>
+ {
+ if (useDiscriminator)
+ {
+ b.Entity()
+ .HasDiscriminator(m => m.Discriminator)
+ .HasValue(EntityType.Base);
+ }
+ else
+ {
+ b.Entity();
+ }
+ },
+ onConfiguring: o => o.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)));
+
+ using var context = contextFactory.CreateContext();
context.Database.EnsureCreated();
var entry = await context.AddAsync(new NonStringDiscriminator { Id = 1 });
@@ -1764,8 +1888,8 @@ public async Task Can_have_non_string_property_named_Discriminator(bool useDiscr
if (useDiscriminator)
{
AssertSql(
- context,
- """
+ context,
+ """
SELECT c
FROM root c
WHERE (c["Discriminator"] = 0)
@@ -1785,15 +1909,16 @@ OFFSET 0 LIMIT 1
""");
}
- Fixture.ListLoggerFactory.Clear();
- Assert.Equal(baseEntity, await context.Set()
+ ListLoggerFactory.Clear();
+ Assert.Equal(
+ baseEntity, await context.Set()
.Where(e => e.Discriminator == EntityType.Base).OrderBy(e => e.Id).FirstOrDefaultAsync());
if (useDiscriminator)
{
AssertSql(
- context,
- """
+ context,
+ """
SELECT c
FROM root c
WHERE ((c["Discriminator"] = 0) AND (c["Discriminator"] = 0))
@@ -1804,8 +1929,8 @@ OFFSET 0 LIMIT 1
else
{
AssertSql(
- context,
- """
+ context,
+ """
SELECT c
FROM root c
WHERE (c["Discriminator"] = 0)
@@ -1814,15 +1939,16 @@ OFFSET 0 LIMIT 1
""");
}
- Fixture.ListLoggerFactory.Clear();
- Assert.Equal(baseEntity, await context.Set()
+ ListLoggerFactory.Clear();
+ Assert.Equal(
+ baseEntity, await context.Set()
.Where(e => e.GetType() == typeof(NonStringDiscriminator)).OrderBy(e => e.Id).FirstOrDefaultAsync());
if (useDiscriminator)
{
AssertSql(
- context,
- """
+ context,
+ """
SELECT c
FROM root c
WHERE (c["Discriminator"] = 0)
@@ -1833,8 +1959,8 @@ OFFSET 0 LIMIT 1
else
{
AssertSql(
- context,
- """
+ context,
+ """
SELECT c
FROM root c
ORDER BY c["Id"]
@@ -1842,15 +1968,16 @@ OFFSET 0 LIMIT 1
""");
}
- Fixture.ListLoggerFactory.Clear();
- Assert.Equal(baseEntity, await context.Set()
+ ListLoggerFactory.Clear();
+ Assert.Equal(
+ baseEntity, await context.Set()
.Where(e => e is NonStringDiscriminator).OrderBy(e => e.Id).FirstOrDefaultAsync());
if (useDiscriminator)
{
AssertSql(
- context,
- """
+ context,
+ """
SELECT c
FROM root c
WHERE (c["Discriminator"] = 0)
@@ -1861,8 +1988,8 @@ OFFSET 0 LIMIT 1
else
{
AssertSql(
- context,
- """
+ context,
+ """
SELECT c
FROM root c
ORDER BY c["Id"]
@@ -1883,68 +2010,35 @@ private enum EntityType
Derived
}
- public class NonStringDiscriminatorContext(DbContextOptions dbContextOptions, bool useDiscriminator) : DbContext(dbContextOptions)
- {
- public bool UseDiscriminator { get; } = useDiscriminator;
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.Entity();
- if (UseDiscriminator)
- {
- modelBuilder.Entity()
- .HasDiscriminator(m => m.Discriminator)
- .HasValue(EntityType.Base);
- }
- }
- }
-
private void AssertSql(DbContext context, params string[] expected)
{
var logger = (TestSqlLoggerFactory)context.GetService();
logger.AssertBaseline(expected);
}
- protected TestSqlLoggerFactory TestSqlLoggerFactory
- => (TestSqlLoggerFactory)Fixture.ListLoggerFactory;
-
- protected void AssertSql(params string[] expected)
- => TestSqlLoggerFactory.AssertBaseline(expected);
-
- protected void AssertContainsSql(params string[] expected)
- => TestSqlLoggerFactory.AssertBaseline(expected, assertOrder: false);
-
protected ListLoggerFactory LoggerFactory { get; }
- public class CosmosFixture : ServiceProviderFixtureBase, IAsyncLifetime
- {
- public CosmosFixture()
- {
- TestStore = CosmosTestStore.Create(DatabaseName);
- }
-
- protected override ITestStoreFactory TestStoreFactory
- => CosmosTestStoreFactory.Instance;
-
- public virtual CosmosTestStore TestStore { get; }
+ protected override string StoreName
+ => nameof(EndToEndCosmosTest);
- public DbContextOptions CreateOptions()
- {
- TestStore.Initialize(null, (Func)null);
- ListLoggerFactory.Clear();
- return CreateOptions(TestStore);
- }
-
- protected override bool ShouldLogCategory(string logCategory)
- => logCategory == DbLoggerCategory.Database.Command.Name;
+ protected override ITestStoreFactory TestStoreFactory
+ => CosmosTestStoreFactory.Instance;
- protected override object GetAdditionalModelCacheKey(DbContext context)
- => (context as NonStringDiscriminatorContext)?.UseDiscriminator;
+ protected ContextFactory ContextFactory { get; private set; }
- public Task InitializeAsync()
- => Task.CompletedTask;
-
- public Task DisposeAsync()
- => TestStore.DisposeAsync();
- }
+ protected async Task InitializeAsync(
+ Action onModelCreating,
+ Func onConfiguring = null,
+ Func seed = null,
+ bool sensitiveLogEnabled = true)
+ => ContextFactory = await InitializeAsync(
+ onModelCreating,
+ seed: seed,
+ shouldLogCategory: _ => true,
+ onConfiguring: options =>
+ {
+ options.ConfigureWarnings(w => w.Log(CosmosEventId.SyncNotSupported)).EnableSensitiveDataLogging(sensitiveLogEnabled);
+ onConfiguring?.Invoke(options);
+ }
+ );
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs
index 1906ee1fc5c..2bfef6105d8 100644
--- a/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs
@@ -27,6 +27,51 @@ public override void Find_derived_using_base_set_type_from_store() { }
public override Task Find_derived_using_base_set_type_from_store_async(CancellationType cancellationType)
=> Task.CompletedTask;
+ public override void Find_int_key_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_int_key_from_store());
+
+ public override void Returns_null_for_int_key_not_in_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Returns_null_for_int_key_not_in_store());
+
+ public override void Find_nullable_int_key_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_nullable_int_key_from_store());
+
+ public override void Returns_null_for_nullable_int_key_not_in_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Returns_null_for_nullable_int_key_not_in_store());
+
+ public override void Find_string_key_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_string_key_from_store());
+
+ public override void Returns_null_for_string_key_not_in_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Returns_null_for_string_key_not_in_store());
+
+ public override void Find_composite_key_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_composite_key_from_store());
+
+ public override void Returns_null_for_composite_key_not_in_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Returns_null_for_composite_key_not_in_store());
+
+ public override void Find_base_type_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_base_type_from_store());
+
+ public override void Returns_null_for_base_type_not_in_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Returns_null_for_base_type_not_in_store());
+
+ public override void Find_derived_type_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_derived_type_from_store());
+
+ public override void Returns_null_for_derived_type_not_in_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Returns_null_for_derived_type_not_in_store());
+
+ public override void Find_base_type_using_derived_set_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_base_type_using_derived_set_from_store());
+
+ public override void Find_shadow_key_from_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Find_shadow_key_from_store());
+
+ public override void Returns_null_for_shadow_key_not_in_store()
+ => CosmosTestHelpers.Instance.NoSyncTest(() => base.Returns_null_for_shadow_key_not_in_store());
+
public class FindCosmosTestSet(FindCosmosFixture fixture) : FindCosmosTest(fixture)
{
protected override TestFinder Finder { get; } = new FindViaSetFinder();
diff --git a/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs
index 2abc333e2cf..0de9b43cc0c 100644
--- a/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs
@@ -9,320 +9,321 @@ public class JsonTypesCosmosTest : JsonTypesTestBase
{
// #25765 - the Cosmos type mapping source doesn't support primitive collections, so we end up with a Property
// that has no ElementType; that causes the assertion on the element nullability to fail.
- public override void Can_read_write_collection_of_string_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_string_JSON_values);
+ public override Task Can_read_write_collection_of_string_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_string_JSON_values);
// #25765 - the Cosmos type mapping source doesn't support primitive collections, so we end up with a Property
// that has no ElementType; that causes the assertion on the element nullability to fail.
- public override void Can_read_write_collection_of_binary_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_binary_JSON_values);
+ public override Task Can_read_write_collection_of_binary_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_binary_JSON_values);
// #25765 - the Cosmos type mapping source doesn't support primitive collections, so we end up with a Property
// that has no ElementType; that causes the assertion on the element nullability to fail.
- public override void Can_read_write_collection_of_nullable_string_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_nullable_string_JSON_values);
+ public override Task Can_read_write_collection_of_nullable_string_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_nullable_string_JSON_values);
- public override void Can_read_write_binary_as_collection()
- => Assert.Throws(base.Can_read_write_binary_as_collection);
+ public override Task Can_read_write_binary_as_collection()
+ => Assert.ThrowsAsync(base.Can_read_write_binary_as_collection);
- public override void Can_read_write_collection_of_bool_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_bool_JSON_values);
+ public override Task Can_read_write_collection_of_bool_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_bool_JSON_values);
- public override void Can_read_write_collection_of_byte_enum_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_byte_enum_JSON_values);
+ public override Task Can_read_write_collection_of_byte_enum_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_byte_enum_JSON_values);
- public override void Can_read_write_collection_of_byte_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_byte_JSON_values);
+ public override Task Can_read_write_collection_of_byte_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_byte_JSON_values);
- public override void Can_read_write_collection_of_char_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_char_JSON_values);
+ public override Task Can_read_write_collection_of_char_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_char_JSON_values);
- public override void Can_read_write_collection_of_DateOnly_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_DateOnly_JSON_values);
+ public override Task Can_read_write_collection_of_DateOnly_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_DateOnly_JSON_values);
- public override void Can_read_write_collection_of_DateTime_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_DateTime_JSON_values);
+ public override Task Can_read_write_collection_of_DateTime_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_DateTime_JSON_values);
- public override void Can_read_write_collection_of_DateTimeOffset_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_DateTimeOffset_JSON_values);
+ public override Task Can_read_write_collection_of_DateTimeOffset_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_DateTimeOffset_JSON_values);
- public override void Can_read_write_collection_of_decimal_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_decimal_JSON_values);
+ public override Task Can_read_write_collection_of_decimal_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_decimal_JSON_values);
- public override void Can_read_write_collection_of_decimal_with_precision_and_scale_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_decimal_with_precision_and_scale_JSON_values);
+ public override Task Can_read_write_collection_of_decimal_with_precision_and_scale_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_decimal_with_precision_and_scale_JSON_values);
- public override void Can_read_write_collection_of_double_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_double_JSON_values);
+ public override Task Can_read_write_collection_of_double_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_double_JSON_values);
- public override void Can_read_write_collection_of_float_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_float_JSON_values);
+ public override Task Can_read_write_collection_of_float_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_float_JSON_values);
- public override void Can_read_write_collection_of_Guid_converted_to_bytes_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_Guid_converted_to_bytes_JSON_values);
+ public override Task Can_read_write_collection_of_Guid_converted_to_bytes_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_Guid_converted_to_bytes_JSON_values);
- public override void Can_read_write_collection_of_GUID_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_GUID_JSON_values);
+ public override Task Can_read_write_collection_of_GUID_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_GUID_JSON_values);
- public override void Can_read_write_collection_of_int_enum_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_int_enum_JSON_values);
+ public override Task Can_read_write_collection_of_int_enum_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_int_enum_JSON_values);
- public override void Can_read_write_collection_of_int_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_int_JSON_values);
+ public override Task Can_read_write_collection_of_int_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_int_JSON_values);
- public override void Can_read_write_collection_of_int_with_converter_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_int_with_converter_JSON_values);
+ public override Task Can_read_write_collection_of_int_with_converter_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_int_with_converter_JSON_values);
- public override void Can_read_write_collection_of_long_enum_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_long_enum_JSON_values);
+ public override Task Can_read_write_collection_of_long_enum_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_long_enum_JSON_values);
- public override void Can_read_write_collection_of_long_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_long_JSON_values);
+ public override Task Can_read_write_collection_of_long_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_long_JSON_values);
- public override void Can_read_write_collection_of_nullable_binary_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_nullable_binary_JSON_values);
+ public override Task Can_read_write_collection_of_nullable_binary_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_nullable_binary_JSON_values);
- public override void Can_read_write_collection_of_nullable_bool_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_nullable_bool_JSON_values);
+ public override Task Can_read_write_collection_of_nullable_bool_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_nullable_bool_JSON_values);
- public override void Can_read_write_collection_of_nullable_byte_enum_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_nullable_byte_enum_JSON_values);
+ public override Task Can_read_write_collection_of_nullable_byte_enum_JSON_values()
+ => Assert.ThrowsAsync(base.Can_read_write_collection_of_nullable_byte_enum_JSON_values);
- public override void Can_read_write_collection_of_nullable_byte_JSON_values()
- => Assert.Throws(base.Can_read_write_collection_of_nullable_byte_JSON_values);
+ public override Task Can_read_write_collection_of_nullable_byte_JSON_values()
+ => Assert.ThrowsAsync