diff --git a/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs b/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs
index b396ce16b2f..e26e454ba6d 100644
--- a/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs
+++ b/src/EFCore.Cosmos/Infrastructure/CosmosDbContextOptionsBuilder.cs
@@ -65,6 +65,17 @@ public virtual CosmosDbContextOptionsBuilder ExecutionStrategy(
public virtual CosmosDbContextOptionsBuilder Region(string region)
=> WithOption(e => e.WithRegion(Check.NotNull(region, nameof(region))));
+ ///
+ /// Configures the context to use the provided preferred regions for geo-replicated database accounts.
+ ///
+ ///
+ /// See Using DbContextOptions, and
+ /// Accessing Azure Cosmos DB with EF Core for more information and examples.
+ ///
+ /// A list of Azure Cosmos DB region names.
+ public virtual CosmosDbContextOptionsBuilder PreferredRegions(IReadOnlyList regions)
+ => WithOption(e => e.WithPreferredRegions(Check.NotNull(regions, nameof(regions))));
+
///
/// Limits the operations to the provided endpoint.
///
diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs
index 33c4c7588f0..9a7792b57e5 100644
--- a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs
+++ b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosDbOptionExtension.cs
@@ -23,6 +23,7 @@ public class CosmosOptionsExtension : IDbContextOptionsExtension
private string? _connectionString;
private string? _databaseName;
private string? _region;
+ private IReadOnlyList? _preferredRegions;
private ConnectionMode? _connectionMode;
private bool? _limitToEndpoint;
private Func? _executionStrategyFactory;
@@ -61,6 +62,7 @@ protected CosmosOptionsExtension(CosmosOptionsExtension copyFrom)
_databaseName = copyFrom._databaseName;
_connectionString = copyFrom._connectionString;
_region = copyFrom._region;
+ _preferredRegions = copyFrom._preferredRegions;
_connectionMode = copyFrom._connectionMode;
_limitToEndpoint = copyFrom._limitToEndpoint;
_executionStrategyFactory = copyFrom._executionStrategyFactory;
@@ -247,6 +249,30 @@ public virtual CosmosOptionsExtension WithRegion(string? region)
return clone;
}
+ ///
+ /// 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 virtual IReadOnlyList? PreferredRegions
+ => _preferredRegions;
+
+ ///
+ /// 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 virtual CosmosOptionsExtension WithPreferredRegions(IReadOnlyList? regions)
+ {
+ var clone = Clone();
+
+ clone._preferredRegions = regions;
+
+ return clone;
+ }
+
///
/// 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/Infrastructure/Internal/CosmosSingletonOptions.cs b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs
index 22f657166c6..4426c1ecc9c 100644
--- a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs
+++ b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosSingletonOptions.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections;
using System.Net;
using Azure.Core;
@@ -54,6 +55,14 @@ public class CosmosSingletonOptions : ICosmosSingletonOptions
///
public virtual string? Region { get; private set; }
+ ///
+ /// 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 virtual IReadOnlyList? PreferredRegions { get; private set; }
+
///
/// 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
@@ -158,6 +167,7 @@ public virtual void Initialize(IDbContextOptions options)
TokenCredential = cosmosOptions.TokenCredential;
ConnectionString = cosmosOptions.ConnectionString;
Region = cosmosOptions.Region;
+ PreferredRegions = cosmosOptions.PreferredRegions;
LimitToEndpoint = cosmosOptions.LimitToEndpoint;
EnableContentResponseOnWrite = cosmosOptions.EnableContentResponseOnWrite;
ConnectionMode = cosmosOptions.ConnectionMode;
@@ -188,6 +198,7 @@ public virtual void Validate(IDbContextOptions options)
|| TokenCredential != cosmosOptions.TokenCredential
|| ConnectionString != cosmosOptions.ConnectionString
|| Region != cosmosOptions.Region
+ || !StructuralComparisons.StructuralEqualityComparer.Equals(PreferredRegions, cosmosOptions.PreferredRegions)
|| LimitToEndpoint != cosmosOptions.LimitToEndpoint
|| ConnectionMode != cosmosOptions.ConnectionMode
|| WebProxy != cosmosOptions.WebProxy
diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs b/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs
index b38e4f40993..a26b79a82b3 100644
--- a/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs
+++ b/src/EFCore.Cosmos/Infrastructure/Internal/ICosmosSingletonOptions.cs
@@ -60,6 +60,14 @@ public interface ICosmosSingletonOptions : ISingletonOptions
///
string? Region { get; }
+ ///
+ /// 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.
+ ///
+ IReadOnlyList? PreferredRegions { get; }
+
///
/// 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/Storage/Internal/SingletonCosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs
index bc4f620c922..4e99f2e0b00 100644
--- a/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs
+++ b/src/EFCore.Cosmos/Storage/Internal/SingletonCosmosClientWrapper.cs
@@ -41,6 +41,11 @@ public SingletonCosmosClientWrapper(ICosmosSingletonOptions options)
configuration.ApplicationRegion = options.Region;
}
+ if (options.PreferredRegions != null)
+ {
+ configuration.ApplicationPreferredRegions = options.PreferredRegions;
+ }
+
if (options.LimitToEndpoint != null)
{
configuration.LimitToEndpoint = options.LimitToEndpoint.Value;
diff --git a/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs b/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs
index 963951c2409..708056c3270 100644
--- a/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs
+++ b/test/EFCore.Cosmos.Tests/Extensions/CosmosDbContextOptionsExtensionsTests.cs
@@ -71,6 +71,8 @@ public void Can_create_options_with_valid_values()
Test(o => o.Region(Regions.EastAsia), o => Assert.Equal(Regions.EastAsia, o.Region));
// The region will be validated by the Cosmos SDK, because the region list is not constant
Test(o => o.Region("FakeRegion"), o => Assert.Equal("FakeRegion", o.Region));
+ Test(o => o.PreferredRegions(new[] { Regions.AustraliaCentral, Regions.EastAsia }),
+ o => Assert.Equal(new[] { Regions.AustraliaCentral, Regions.EastAsia }, o.PreferredRegions));
Test(o => o.ConnectionMode(ConnectionMode.Direct), o => Assert.Equal(ConnectionMode.Direct, o.ConnectionMode));
Test(o => o.GatewayModeMaxConnectionLimit(3), o => Assert.Equal(3, o.GatewayModeMaxConnectionLimit));
Test(o => o.MaxRequestsPerTcpConnection(3), o => Assert.Equal(3, o.MaxRequestsPerTcpConnection));