From a22455887f53a5e7a22c948f4f0bd1343a17d024 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Sep 2025 20:08:57 +0000 Subject: [PATCH 1/7] Initial plan From e8212626b1d5bf9fcd482bd4d8eefb284bd25a63 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Sep 2025 20:16:55 +0000 Subject: [PATCH 2/7] Add documentation for Cosmos trigger execution Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../core/providers/cosmos/modeling.md | 22 ++++++++ .../Cosmos/ModelBuilding/TriggerSample.cs | 51 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 samples/core/Cosmos/ModelBuilding/TriggerSample.cs diff --git a/entity-framework/core/providers/cosmos/modeling.md b/entity-framework/core/providers/cosmos/modeling.md index 2ceebf6728..1ae4712f36 100644 --- a/entity-framework/core/providers/cosmos/modeling.md +++ b/entity-framework/core/providers/cosmos/modeling.md @@ -325,6 +325,28 @@ Limitations: * Only dictionaries with string keys are supported. * Support for querying into primitive collections was added in EF Core 9.0. +## Database triggers + +> [!NOTE] +> Database trigger execution support was introduced in EF Core 9.0. + +Azure Cosmos DB supports pre- and post-triggers that run before or after database operations. EF Core can be configured to execute these triggers when performing save operations. + +> [!IMPORTANT] +> Triggers are executed client-side by EF Core and are not enforced server-side by Azure Cosmos DB. This means triggers should not be used for security-related functionality such as authentication or auditing, as they can be bypassed by applications that access the database directly without using EF Core. + +To configure triggers on an entity type, use the method: + +[!code-csharp[TriggerConfiguration](../../../../samples/core/Cosmos/ModelBuilding/TriggerSample.cs?name=TriggerConfiguration)] + +The `HasTrigger` method requires: + +* **modelName**: The name of the trigger in Azure Cosmos DB +* **triggerType**: Either `TriggerType.Pre` (executed before the operation) or `TriggerType.Post` (executed after the operation) +* **triggerOperation**: The operation that should execute the trigger - `Create`, `Replace`, `Delete`, or `All` + +Before triggers can be executed, they must be created in Azure Cosmos DB using the Cosmos SDK or Azure portal. The trigger name configured in EF Core must match the trigger name in Azure Cosmos DB. + ## Optimistic concurrency with eTags To configure an entity type to use [optimistic concurrency](xref:core/saving/concurrency) call . This call will create an `_etag` property in [shadow state](xref:core/modeling/shadow-properties) and set it as the concurrency token. diff --git a/samples/core/Cosmos/ModelBuilding/TriggerSample.cs b/samples/core/Cosmos/ModelBuilding/TriggerSample.cs new file mode 100644 index 0000000000..d6e531bf03 --- /dev/null +++ b/samples/core/Cosmos/ModelBuilding/TriggerSample.cs @@ -0,0 +1,51 @@ +using Microsoft.Azure.Cosmos.Scripts; +using Microsoft.EntityFrameworkCore; + +namespace Cosmos.ModelBuilding; + +public static class TriggerSample +{ + public static void ConfigureTriggers() + { + var contextOptions = new DbContextOptionsBuilder() + .UseCosmos("https://localhost:8081", "account-key", "sample"); + + using var context = new TriggerContext(contextOptions.Options); + + // Triggers would be configured in OnModelCreating when the API is available + } +} + +public class TriggerContext : DbContext +{ + public TriggerContext(DbContextOptions options) : base(options) { } + + public DbSet Products { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + #region TriggerConfiguration + modelBuilder.Entity(entity => + { + entity.HasPartitionKey(p => p.Category); + + // Configure pre-trigger for create operations (EF Core 9+) + // entity.HasTrigger("PreInsertTrigger", TriggerType.Pre, TriggerOperation.Create); + + // Configure post-trigger for delete operations (EF Core 9+) + // entity.HasTrigger("PostDeleteTrigger", TriggerType.Post, TriggerOperation.Delete); + + // Configure trigger for replace operations (EF Core 9+) + // entity.HasTrigger("UpdateTrigger", TriggerType.Pre, TriggerOperation.Replace); + }); + #endregion + } +} + +public class Product +{ + public int Id { get; set; } + public string Name { get; set; } = null!; + public decimal Price { get; set; } + public string Category { get; set; } = null!; +} \ No newline at end of file From 5222db127557c1f01b8efda54fda6816e507a05f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:54:47 +0000 Subject: [PATCH 3/7] Address review feedback: Update version to 10.0, clarify server-side execution, remove xref link, and enhance sample code Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../core/providers/cosmos/modeling.md | 6 ++-- .../Cosmos/ModelBuilding/TriggerSample.cs | 36 +++++++++++++++---- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/entity-framework/core/providers/cosmos/modeling.md b/entity-framework/core/providers/cosmos/modeling.md index 1ae4712f36..e4b237bcae 100644 --- a/entity-framework/core/providers/cosmos/modeling.md +++ b/entity-framework/core/providers/cosmos/modeling.md @@ -328,14 +328,14 @@ Limitations: ## Database triggers > [!NOTE] -> Database trigger execution support was introduced in EF Core 9.0. +> Database trigger execution support was introduced in EF Core 10.0. Azure Cosmos DB supports pre- and post-triggers that run before or after database operations. EF Core can be configured to execute these triggers when performing save operations. > [!IMPORTANT] -> Triggers are executed client-side by EF Core and are not enforced server-side by Azure Cosmos DB. This means triggers should not be used for security-related functionality such as authentication or auditing, as they can be bypassed by applications that access the database directly without using EF Core. +> Triggers are executed server-side by Azure Cosmos DB when EF Core performs operations, but they are not enforced - operations can be performed without running triggers if accessing the database directly. This means triggers should not be used for security-related functionality such as authentication or auditing, as they can be bypassed by applications that access the database directly without using EF Core. -To configure triggers on an entity type, use the method: +To configure triggers on an entity type, use the `HasTrigger` method: [!code-csharp[TriggerConfiguration](../../../../samples/core/Cosmos/ModelBuilding/TriggerSample.cs?name=TriggerConfiguration)] diff --git a/samples/core/Cosmos/ModelBuilding/TriggerSample.cs b/samples/core/Cosmos/ModelBuilding/TriggerSample.cs index d6e531bf03..b17d1efc25 100644 --- a/samples/core/Cosmos/ModelBuilding/TriggerSample.cs +++ b/samples/core/Cosmos/ModelBuilding/TriggerSample.cs @@ -1,18 +1,40 @@ using Microsoft.Azure.Cosmos.Scripts; using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; namespace Cosmos.ModelBuilding; public static class TriggerSample { - public static void ConfigureTriggers() + public static async Task ConfigureTriggers() { var contextOptions = new DbContextOptionsBuilder() .UseCosmos("https://localhost:8081", "account-key", "sample"); using var context = new TriggerContext(contextOptions.Options); - // Triggers would be configured in OnModelCreating when the API is available + // Ensure database is created + await context.Database.EnsureCreatedAsync(); + + // Create a new product - this will trigger the PreInsertTrigger + var product = new Product + { + Id = 1, + Name = "Sample Product", + Price = 19.99m, + Category = "Electronics" + }; + + context.Products.Add(product); + await context.SaveChangesAsync(); + + // Update the product - this will trigger the UpdateTrigger + product.Price = 24.99m; + await context.SaveChangesAsync(); + + // Delete the product - this will trigger the PostDeleteTrigger + context.Products.Remove(product); + await context.SaveChangesAsync(); } } @@ -24,21 +46,21 @@ public TriggerContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { - #region TriggerConfiguration modelBuilder.Entity(entity => { entity.HasPartitionKey(p => p.Category); - // Configure pre-trigger for create operations (EF Core 9+) + #region TriggerConfiguration + // Configure pre-trigger for create operations (requires EF Core 10.0+ and .NET 10) // entity.HasTrigger("PreInsertTrigger", TriggerType.Pre, TriggerOperation.Create); - // Configure post-trigger for delete operations (EF Core 9+) + // Configure post-trigger for delete operations (requires EF Core 10.0+ and .NET 10) // entity.HasTrigger("PostDeleteTrigger", TriggerType.Post, TriggerOperation.Delete); - // Configure trigger for replace operations (EF Core 9+) + // Configure trigger for replace operations (requires EF Core 10.0+ and .NET 10) // entity.HasTrigger("UpdateTrigger", TriggerType.Pre, TriggerOperation.Replace); + #endregion }); - #endregion } } From c7a215cbe358b0c0a94615f2b42ad7a78ecc914d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Sep 2025 23:21:11 +0000 Subject: [PATCH 4/7] Configure project for .NET 10 and uncomment HasTrigger methods Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- global.json | 5 +++++ samples/core/Cosmos/Cosmos.csproj | 4 ++-- .../core/Cosmos/ModelBuilding/TriggerSample.cs | 12 ++++++------ samples/core/Cosmos/README.md | 15 +++++++++++++++ 4 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 global.json create mode 100644 samples/core/Cosmos/README.md diff --git a/global.json b/global.json new file mode 100644 index 0000000000..be4942c34f --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "10.0.100-rc.1.25451.107" + } +} \ No newline at end of file diff --git a/samples/core/Cosmos/Cosmos.csproj b/samples/core/Cosmos/Cosmos.csproj index 8539b9f9df..7ba28aaa96 100644 --- a/samples/core/Cosmos/Cosmos.csproj +++ b/samples/core/Cosmos/Cosmos.csproj @@ -2,11 +2,11 @@ Exe - net8.0 + net10.0 - + diff --git a/samples/core/Cosmos/ModelBuilding/TriggerSample.cs b/samples/core/Cosmos/ModelBuilding/TriggerSample.cs index b17d1efc25..68a75e5ae9 100644 --- a/samples/core/Cosmos/ModelBuilding/TriggerSample.cs +++ b/samples/core/Cosmos/ModelBuilding/TriggerSample.cs @@ -51,14 +51,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.HasPartitionKey(p => p.Category); #region TriggerConfiguration - // Configure pre-trigger for create operations (requires EF Core 10.0+ and .NET 10) - // entity.HasTrigger("PreInsertTrigger", TriggerType.Pre, TriggerOperation.Create); + // Configure pre-trigger for create operations + entity.HasTrigger("PreInsertTrigger", TriggerType.Pre, TriggerOperation.Create); - // Configure post-trigger for delete operations (requires EF Core 10.0+ and .NET 10) - // entity.HasTrigger("PostDeleteTrigger", TriggerType.Post, TriggerOperation.Delete); + // Configure post-trigger for delete operations + entity.HasTrigger("PostDeleteTrigger", TriggerType.Post, TriggerOperation.Delete); - // Configure trigger for replace operations (requires EF Core 10.0+ and .NET 10) - // entity.HasTrigger("UpdateTrigger", TriggerType.Pre, TriggerOperation.Replace); + // Configure trigger for replace operations + entity.HasTrigger("UpdateTrigger", TriggerType.Pre, TriggerOperation.Replace); #endregion }); } diff --git a/samples/core/Cosmos/README.md b/samples/core/Cosmos/README.md new file mode 100644 index 0000000000..7d05fa6f8f --- /dev/null +++ b/samples/core/Cosmos/README.md @@ -0,0 +1,15 @@ +# Cosmos Sample + +This sample demonstrates Azure Cosmos DB features with Entity Framework Core. + +## Requirements for Trigger Feature + +The trigger execution feature (`HasTrigger` methods) requires: +- .NET 10.0 SDK (10.0.100-rc.1.25451.107 or later) +- EF Core 10.0.0-rc.1.25451.107 or later + +The project is configured to use these versions, but the code may not compile in environments without .NET 10 SDK installed. + +## Building + +To build this sample, ensure you have the .NET 10 SDK installed. If not available, comment out the `HasTrigger` method calls in `TriggerSample.cs`. \ No newline at end of file From f51571882434fb8f8f05adf554bf2c35acb89ee9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Sep 2025 23:35:25 +0000 Subject: [PATCH 5/7] Move global.json to samples/ folder and remove Cosmos README.md Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- samples/core/Cosmos/README.md | 15 --------------- global.json => samples/global.json | 0 2 files changed, 15 deletions(-) delete mode 100644 samples/core/Cosmos/README.md rename global.json => samples/global.json (100%) diff --git a/samples/core/Cosmos/README.md b/samples/core/Cosmos/README.md deleted file mode 100644 index 7d05fa6f8f..0000000000 --- a/samples/core/Cosmos/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Cosmos Sample - -This sample demonstrates Azure Cosmos DB features with Entity Framework Core. - -## Requirements for Trigger Feature - -The trigger execution feature (`HasTrigger` methods) requires: -- .NET 10.0 SDK (10.0.100-rc.1.25451.107 or later) -- EF Core 10.0.0-rc.1.25451.107 or later - -The project is configured to use these versions, but the code may not compile in environments without .NET 10 SDK installed. - -## Building - -To build this sample, ensure you have the .NET 10 SDK installed. If not available, comment out the `HasTrigger` method calls in `TriggerSample.cs`. \ No newline at end of file diff --git a/global.json b/samples/global.json similarity index 100% rename from global.json rename to samples/global.json From aa59831d88ec30c5f8a673a914bb0ad0c23a7c6e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Sep 2025 19:20:17 +0000 Subject: [PATCH 6/7] Update ms.date in modeling.md header to 09/26/2024 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- entity-framework/core/providers/cosmos/modeling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entity-framework/core/providers/cosmos/modeling.md b/entity-framework/core/providers/cosmos/modeling.md index e4b237bcae..79b292b1a7 100644 --- a/entity-framework/core/providers/cosmos/modeling.md +++ b/entity-framework/core/providers/cosmos/modeling.md @@ -2,7 +2,7 @@ title: Modeling - Azure Cosmos DB Provider - EF Core description: Configuring the model with the Azure Cosmos DB EF Core Provider author: roji -ms.date: 09/19/2024 +ms.date: 09/26/2024 uid: core/providers/cosmos/modeling --- # Configuring the model with the EF Core Azure Cosmos DB Provider From ab064992e2a06065b20d4e812f94f9e7fc4cc459 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:42:12 +0000 Subject: [PATCH 7/7] Move Database triggers section to bottom of page Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../core/providers/cosmos/modeling.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/entity-framework/core/providers/cosmos/modeling.md b/entity-framework/core/providers/cosmos/modeling.md index 79b292b1a7..119775be25 100644 --- a/entity-framework/core/providers/cosmos/modeling.md +++ b/entity-framework/core/providers/cosmos/modeling.md @@ -325,6 +325,16 @@ Limitations: * Only dictionaries with string keys are supported. * Support for querying into primitive collections was added in EF Core 9.0. +## Optimistic concurrency with eTags + +To configure an entity type to use [optimistic concurrency](xref:core/saving/concurrency) call . This call will create an `_etag` property in [shadow state](xref:core/modeling/shadow-properties) and set it as the concurrency token. + +[!code-csharp[Main](../../../../samples/core/Cosmos/ModelBuilding/OrderContext.cs?name=ETag)] + +To make it easier to resolve concurrency errors you can map the eTag to a CLR property using . + +[!code-csharp[Main](../../../../samples/core/Cosmos/ModelBuilding/OrderContext.cs?name=ETagProperty)] + ## Database triggers > [!NOTE] @@ -346,13 +356,3 @@ The `HasTrigger` method requires: * **triggerOperation**: The operation that should execute the trigger - `Create`, `Replace`, `Delete`, or `All` Before triggers can be executed, they must be created in Azure Cosmos DB using the Cosmos SDK or Azure portal. The trigger name configured in EF Core must match the trigger name in Azure Cosmos DB. - -## Optimistic concurrency with eTags - -To configure an entity type to use [optimistic concurrency](xref:core/saving/concurrency) call . This call will create an `_etag` property in [shadow state](xref:core/modeling/shadow-properties) and set it as the concurrency token. - -[!code-csharp[Main](../../../../samples/core/Cosmos/ModelBuilding/OrderContext.cs?name=ETag)] - -To make it easier to resolve concurrency errors you can map the eTag to a CLR property using . - -[!code-csharp[Main](../../../../samples/core/Cosmos/ModelBuilding/OrderContext.cs?name=ETagProperty)]