diff --git a/entity-framework/core/cli/powershell.md b/entity-framework/core/cli/powershell.md index 5d5fda04b0..55bd24db27 100644 --- a/entity-framework/core/cli/powershell.md +++ b/entity-framework/core/cli/powershell.md @@ -11,7 +11,9 @@ The Package Manager Console (PMC) tools for Entity Framework Core perform design If you aren't using Visual Studio, we recommend the [EF Core Command-line Tools](xref:core/cli/dotnet) instead. The .NET Core CLI tools are cross-platform and run inside a command prompt. -## Installing the tools +[!INCLUDE [managed-identities-test-non-production](~/core/includes/managed-identities-test-non-production.md)] + +## Install the tools Install the Package Manager Console tools by running the following command in **Package Manager Console**: @@ -53,7 +55,7 @@ SHORT DESCRIPTION ``` -## Using the tools +## Use the tools Before using the tools: @@ -215,7 +217,7 @@ Parameters: | Parameter | Description | |:------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `-Connection ` | The connection string to the database. For ASP.NET Core 2.x projects, the value can be *name=\*. In that case the name comes from the configuration sources that are set up for the project. This is a positional parameter and is required. | +| `-Connection ` | The connection string to the database. The value can be *name=\*. In that case the name comes from the [configuration sources](xref:core/miscellaneous/connection-strings#aspnet-core) that are set up for the project. This is a positional parameter and is required. | | `-Provider ` | The provider to use. Typically this is the name of the NuGet package, for example: `Microsoft.EntityFrameworkCore.SqlServer`. This is a positional parameter and is required. | | `-OutputDir ` | The directory to put entity class files in. Paths are relative to the project directory. | | `-ContextDir ` | The directory to put the `DbContext` file in. Paths are relative to the project directory. | diff --git a/entity-framework/core/dbcontext-configuration/index.md b/entity-framework/core/dbcontext-configuration/index.md index 6bc1d0ba33..82483359f5 100644 --- a/entity-framework/core/dbcontext-configuration/index.md +++ b/entity-framework/core/dbcontext-configuration/index.md @@ -10,6 +10,8 @@ uid: core/dbcontext-configuration/index This article shows basic patterns for initialization and configuration of a instance. +[!INCLUDE [managed-identities-test-non-production](~/core/includes/managed-identities-test-non-production.md)] + ## The DbContext lifetime The lifetime of a `DbContext` begins when the instance is created and ends when the instance is [disposed](/dotnet/standard/garbage-collection/unmanaged). A `DbContext` instance is designed to be used for a _single_ [unit-of-work](https://www.martinfowler.com/eaaCatalog/unitOfWork.html). This means that the lifetime of a `DbContext` instance is usually very short. @@ -29,15 +31,17 @@ A typical unit-of-work when using Entity Framework Core (EF Core) involves: > [!IMPORTANT] > -> - It is very important to dispose the after use. This ensures both that any unmanaged resources are freed, and that any events or other hooks are unregistered so as to prevent memory leaks in case the instance remains referenced. -> - [DbContext is **not thread-safe**](#avoiding-dbcontext-threading-issues). Do not share contexts between threads. Make sure to [await](/dotnet/csharp/language-reference/operators/await) all async calls before continuing to use the context instance. +> - It is important to dispose the after use. This ensures any: +> - Unmanaged resources are freed. +> - Events or other hooks are unregistered. Unregistering prevents memory leaks when the instance remains referenced. +> - [DbContext is **Not thread-safe**](#avoiding-dbcontext-threading-issues). Don't share contexts between threads. Make sure to [await](/dotnet/csharp/language-reference/operators/await) all async calls before continuing to use the context instance. > - An thrown by EF Core code can put the context into an unrecoverable state. Such exceptions indicate a program error and are not designed to be recovered from. ## DbContext in dependency injection for ASP.NET Core In many web applications, each HTTP request corresponds to a single unit-of-work. This makes tying the context lifetime to that of the request a good default for web applications. -ASP.NET Core applications are [configured using dependency injection](/aspnet/core/fundamentals/startup). EF Core can be added to this configuration using in the [`ConfigureServices`](/aspnet/core/fundamentals/startup#the-configureservices-method) method of `Startup.cs`. For example: +ASP.NET Core applications are [configured using dependency injection](/aspnet/core/fundamentals/startup). EF Core can be added to this configuration using in `Program.cs`. For example: -[!code-csharp[ConfigureServices](../../../samples/core/Miscellaneous/ConfiguringDbContext/WebApp/Startup.cs?name=ConfigureServices)] -This example registers a `DbContext` subclass called `ApplicationDbContext` as a scoped service in the ASP.NET Core application service provider (a.k.a. the dependency injection container). The context is configured to use the SQL Server database provider and will read the connection string from ASP.NET Core configuration. It typically does not matter _where_ in `ConfigureServices` the call to `AddDbContext` is made. +[!code-csharp[snippet_1](../../../samples/core/Miscellaneous/ConfiguringDbContext/WebApp9/Program9.cs?name=snippet_1)] + +The preceding code registers `ApplicationDbContext`, a subclass of `DbContext`, as a scoped service in the ASP.NET Core app service provider. The service provider is also known as the dependency injection container. The context is configured to use the SQL Server database provider and reads the connection string from ASP.NET Core configuration. The `ApplicationDbContext` class must expose a public constructor with a `DbContextOptions` parameter. This is how context configuration from `AddDbContext` is passed to the `DbContext`. For example: @@ -63,9 +68,10 @@ The `ApplicationDbContext` class must expose a public constructor with a `DbCont } } --> + [!code-csharp[ApplicationDbContext](../../../samples/core/Miscellaneous/ConfiguringDbContext/WebApp/ApplicationDbContext.cs?name=ApplicationDbContext)] -`ApplicationDbContext` can then be used in ASP.NET Core controllers or other services through constructor injection. For example: +`ApplicationDbContext` can be used in ASP.NET Core controllers or other services through constructor injection: -## Simple DbContext initialization with 'new' +## Basic DbContext initialization with 'new' -`DbContext` instances can be constructed in the normal .NET way, for example with `new` in C#. Configuration can be performed by overriding the `OnConfiguring` method, or by passing options to the constructor. For example: +`DbContext` instances can be constructed with `new` in C#. Configuration can be performed by overriding the `OnConfiguring` method, or by passing options to the constructor. For example: [!code-csharp[UseNewForWebApp](../../../samples/core/Miscellaneous/ConfiguringDbContext/WebApp/UseNewForWebApp.cs?name=UseNewForWebApp)] -## Using a DbContext factory (e.g. for Blazor) +## Use a DbContext factory Some application types (e.g. [ASP.NET Core Blazor](/aspnet/core/blazor/)) use dependency injection but do not create a service scope that aligns with the desired `DbContext` lifetime. Even where such an alignment does exist, the application may need to perform multiple units-of-work within this scope. For example, multiple units-of-work within a single HTTP request. diff --git a/entity-framework/core/includes/managed-identities-test-non-production.md b/entity-framework/core/includes/managed-identities-test-non-production.md index 42ec1496a8..1a7c06c5d3 100644 --- a/entity-framework/core/includes/managed-identities-test-non-production.md +++ b/entity-framework/core/includes/managed-identities-test-non-production.md @@ -4,6 +4,7 @@ author: rick-anderson ms.author: riande ms.date: 10/23/2024 ms.topic: include +title: an include file --- > [!WARNING] -> This article uses a local database that doesn't require the user to be authenticated. Production apps should use the most secure authentication flow available. For more information on authentication for deployed test and production apps, see [Secure authentication flows](xref:security/index#secure-authentication-flows). +> This article uses a local database that doesn't require the user to be authenticated. Production apps should use the most secure authentication flow available. For more information on authentication for deployed test and production apps, see [Secure authentication flows](/aspnet/core/security/#secure-authentication-flows). diff --git a/entity-framework/core/index.md b/entity-framework/core/index.md index cf68985f76..24f47ebcb1 100644 --- a/entity-framework/core/index.md +++ b/entity-framework/core/index.md @@ -50,7 +50,7 @@ While EF Core is good at abstracting many programming details, there are some be * Find issues in the app that only show up when using a specific versions or edition of the database server. * Catch breaking changes when upgrading EF Core and other dependencies. For example, adding or upgrading frameworks like ASP.NET Core, OData, or AutoMapper. These dependencies can affect EF Core in unexpected ways. * Performance and stress testing with representative loads. The naïve usage of some features doesn't scale well. For example, multiple collections Includes, heavy use of lazy loading, conditional queries on non-indexed columns, massive updates and inserts with store-generated values, lack of concurrency handling, large models, inadequate cache policy. -* Security review: For example, handling of connection strings and other secrets, database permissions for non-deployment operation, input validation for raw SQL, encryption for sensitive data. +* Security review: For example, handling of connection strings and other secrets, database permissions for non-deployment operation, input validation for raw SQL, encryption for sensitive data. See [Secure authentication flows](/aspnet/core/security/#secure-authentication-flows) for secure configuration and authentication flow. * Make sure logging and diagnostics are sufficient and usable. For example, appropriate logging configuration, query tags, and Application Insights. * Error recovery. Prepare contingencies for common failure scenarios such as version rollback, fallback servers, scale-out and load balancing, DoS mitigation, and data backups. * Application deployment and migration. Plan out how migrations are going to be applied during deployment; doing it at application start can suffer from concurrency issues and requires higher permissions than necessary for normal operation. Use staging to facilitate recovery from fatal errors during migration. For more information, see [Applying Migrations](xref:core/managing-schemas/migrations/applying). diff --git a/entity-framework/core/managing-schemas/migrations/applying.md b/entity-framework/core/managing-schemas/migrations/applying.md index 0539ffad76..ed3e45c97a 100644 --- a/entity-framework/core/managing-schemas/migrations/applying.md +++ b/entity-framework/core/managing-schemas/migrations/applying.md @@ -222,10 +222,10 @@ Options: | `--no-color` | | Don't colorize output. | | `--prefix-output` | | Prefix output with level. | -The following example applies migrations to a local SQL Server instance using the specified username and password. +The following example applies migrations to a local SQL Server instance using the specified username and credentials: ```powershell -.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password=myPassword' +.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password={;'$Credential;'here'}' ``` > [!WARNING] diff --git a/entity-framework/core/managing-schemas/scaffolding/index.md b/entity-framework/core/managing-schemas/scaffolding/index.md index aaba0bf5c3..7d68a744d9 100644 --- a/entity-framework/core/managing-schemas/scaffolding/index.md +++ b/entity-framework/core/managing-schemas/scaffolding/index.md @@ -7,7 +7,7 @@ uid: core/managing-schemas/scaffolding --- # Scaffolding (Reverse Engineering) -Reverse engineering is the process of scaffolding entity type classes and a `DbContext` class based on a database schema. It can be performed using the `Scaffold-DbContext` command of the EF Core Package Manager Console (PMC) tools or the `dotnet ef dbcontext scaffold` command of the .NET Command-line Interface (CLI) tools. +Reverse engineering is the process of scaffolding entity type classes and a [DbContext](/dotnet/api/microsoft.entityframeworkcore.dbcontext) class based on a database schema. It can be performed using the `Scaffold-DbContext` command of the EF Core Package Manager Console (PMC) tools or the `dotnet ef dbcontext scaffold` command of the .NET Command-line Interface (CLI) tools. > [!NOTE] > The scaffolding of a `DbContext` and entity types documented here is distinct from the [scaffolding of controllers in ASP.NET Core](/aspnet/mvc/overview/getting-started/introduction/adding-a-controller) using Visual Studio, which is not documented here. @@ -27,9 +27,11 @@ Both the PMC and the .NET CLI commands have two required arguments: the connecti ### Connection string -The first argument to the command is a connection string to the database. The tools will use this connection string to read the database schema. +[!INCLUDE [managed-identities-test-non-production](~/core/includes/managed-identities-test-non-production.md)] -How you quote and escape the connection string depends on which shell you are using to execute the command; refer to your shell's documentation for more information. For example, PowerShell requires you to escape the `$` character, but not `\`. +The first argument to the command is a connection string to the database. The tools use this connection string to read the database schema. + +How the connection string is quoted and escaped depends on the shell that is used to run the command. Refer to the shell's documentation. For example, PowerShell requires escaping `$`, but not `\`. The following example scaffolds entity types and a `DbContext` from the `Chinook` database located on the machine's SQL Server LocalDB instance, making use of the `Microsoft.EntityFrameworkCore.SqlServer` database provider. diff --git a/entity-framework/core/miscellaneous/multitenancy.md b/entity-framework/core/miscellaneous/multitenancy.md index 51cd9f7bd4..316f72c430 100644 --- a/entity-framework/core/miscellaneous/multitenancy.md +++ b/entity-framework/core/miscellaneous/multitenancy.md @@ -10,6 +10,8 @@ uid: core/miscellaneous/multitenancy Many line of business applications are designed to work with multiple customers. It is important to secure the data so that customer data isn't "leaked" or seen by other customers and potential competitors. These applications are classified as "multi-tenant" because each customer is considered a tenant of the application with their own set of data. +[!INCLUDE [managed-identities-test-non-production](~/core/includes/managed-identities-test-non-production.md)] + > [!IMPORTANT] > This document provides examples and solutions "as is." These are not intended to be "best practices" but rather "working practices" for your consideration. diff --git a/entity-framework/ef6/fundamentals/configuring/config-file.md b/entity-framework/ef6/fundamentals/configuring/config-file.md index 68020abc09..89fba22d06 100644 --- a/entity-framework/ef6/fundamentals/configuring/config-file.md +++ b/entity-framework/ef6/fundamentals/configuring/config-file.md @@ -6,7 +6,16 @@ ms.date: 10/23/2016 uid: ef6/fundamentals/configuring/config-file --- # Configuration File Settings -Entity Framework allows a number of settings to be specified from the configuration file. In general EF follows a ‘convention over configuration’ principle: all the settings discussed in this post have a default behavior, you only need to worry about changing the setting when the default no longer satisfies your requirements. +Entity Framework allows a number of settings to be specified from the configuration file. In general EF follows a ‘convention over configuration’ principle: all the settings discussed in this post have a default behavior, you only need to worry about changing the setting when the default no longer satisfies your requirements. + +## Configuration data guidelines + +* Never store passwords or other sensitive data in configuration provider code or in plain text configuration files. +* Don't use production secrets in development or test environments. +* Specify secrets outside of the project so that they can't be accidentally committed to a source code repository. +* Consider protecting the contents of the configuration file using [Protected Configuration](/dotnet/framework/data/adonet/connection-strings-and-configuration-files#encrypt-configuration-file-sections-using-protected-configuration). + +[!INCLUDE [managed-identities-test-non-production](~/core/includes/managed-identities-test-non-production.md)] ## A Code-Based Alternative diff --git a/entity-framework/ef6/fundamentals/configuring/connection-strings.md b/entity-framework/ef6/fundamentals/configuring/connection-strings.md index 20d8b71ba5..383d8fe70b 100644 --- a/entity-framework/ef6/fundamentals/configuring/connection-strings.md +++ b/entity-framework/ef6/fundamentals/configuring/connection-strings.md @@ -6,12 +6,15 @@ ms.date: 10/23/2016 uid: ef6/fundamentals/configuring/connection-strings --- # Connection strings and models -This topic covers how Entity Framework discovers which database connection to use, and how you can change it. Models created with Code First and the EF Designer are both covered in this topic. +This article covers how Entity Framework discovers which database connection to use, and how to change it. Models created with Code First and the EF Designer are covered. -Typically an Entity Framework application uses a class derived from DbContext. This derived class will call one of the constructors on the base DbContext class to control: +[!INCLUDE [managed-identities-test-non-production](~/core/includes/managed-identities-test-non-production.md)] -- How the context will connect to a database — that is, how a connection string is found/used -- Whether the context will use calculate a model using Code First or load a model created with the EF Designer + +Typically an Entity Framework application uses a class derived from DbContext. This derived class calls one of the constructors on the base DbContext class to control: + +- How the context connects to a database, that is, how a connection string is found and used. +- Whether the context calculates a model using Code First or loads a model created with the EF Designer. - Additional advanced options The following fragments show some of the ways the DbContext constructors can be used. diff --git a/entity-framework/ef6/fundamentals/configuring/dependency-resolution.md b/entity-framework/ef6/fundamentals/configuring/dependency-resolution.md index 28e48f3674..75b56b4903 100644 --- a/entity-framework/ef6/fundamentals/configuring/dependency-resolution.md +++ b/entity-framework/ef6/fundamentals/configuring/dependency-resolution.md @@ -58,7 +58,7 @@ This article does not contain full details on how to implement IDbDependencyReso **Version introduced**: EF6.0.0 -**Object returned**: The connection factory that will be used when EF creates a database connection by convention. That is, when no connection or connection string is given to EF, and no connection string can be found in the app.config or web.config, then this service is used to create a connection by convention. Changing the connection factory can allow EF to use a different type of database (for example, SQL Server Compact Edition) by default. +**Object returned**: The connection factory that will be used when EF creates a database connection by convention. That is, when no connection or connection string is given to EF, and no connection string can be found in the `app.config` or `web.config`, then this service is used to create a connection by convention. Changing the connection factory can allow EF to use a different type of database (for example, SQL Server Compact Edition) by default. Never store passwords or other sensitive data in configuration provider code or in plain text configuration files. Specify secrets outside of the project so that they can't be accidentally committed to a source code repository. Consider protecting the contents of the configuration file using [Protected Configuration](/dotnet/framework/data/adonet/connection-strings-and-configuration-files#encrypt-configuration-file-sections-using-protected-configuration). **Key**: Not used; will be null diff --git a/entity-framework/efcore-and-ef6/porting/port-code.md b/entity-framework/efcore-and-ef6/porting/port-code.md index 168f9d994f..8d3667e3c8 100644 --- a/entity-framework/efcore-and-ef6/porting/port-code.md +++ b/entity-framework/efcore-and-ef6/porting/port-code.md @@ -25,7 +25,7 @@ Most APIs that you use in EF6 are in the `System.Data.Entity` namespace (and rel As described in [configuring the database connection](xref:efcore-and-ef6/porting/port-detailed-cases#configuring-the-database-connection), EF Core has less magic around detecting the database to connect to. You will need to override the `OnConfiguring` method on your derived context, and use the database provider specific API to setup the connection to the database. -Most EF6 applications store the connection string in the applications `App/Web.config` file. In EF Core, you read this connection string using the `ConfigurationManager` API. You may need to add a reference to the `System.Configuration` framework assembly to be able to use this API. +Most EF6 applications store the connection string in the applications `App/Web.config` file. In EF Core, you read this connection string using the `ConfigurationManager` API. You may need to add a reference to the `System.Configuration` framework assembly to be able to use this API: ```csharp public class BloggingContext : DbContext @@ -40,6 +40,9 @@ public class BloggingContext : DbContext } ``` +> Warning +> Never store passwords or other sensitive data in source code or configuration files. Production secrets shouldn't be used for development or test. Secrets shouldn't be deployed with the app. Production secrets should be accessed through a controlled means like Azure Key Vault. Azure test and production secrets can be stored and protected with the [Azure Key Vault configuration provider](/aspnet/core/security/key-vault-configuration). + ## Update your code At this point, it's a matter of addressing compilation errors and reviewing code to see if the behavior changes will impact you. diff --git a/samples/core/Miscellaneous/ConfiguringDbContext/WebApp/Program.cs b/samples/core/Miscellaneous/ConfiguringDbContext/WebApp/Program.cs index 5b331a6ad7..e4fbbececf 100644 --- a/samples/core/Miscellaneous/ConfiguringDbContext/WebApp/Program.cs +++ b/samples/core/Miscellaneous/ConfiguringDbContext/WebApp/Program.cs @@ -2,7 +2,7 @@ using Microsoft.Extensions.Hosting; using WebApp; -public class Program +public class Program { public static void Main(string[] args) { diff --git a/samples/core/Miscellaneous/ConfiguringDbContext/WebApp9/Program9.cs b/samples/core/Miscellaneous/ConfiguringDbContext/WebApp9/Program9.cs new file mode 100644 index 0000000000..e6e96ef97c --- /dev/null +++ b/samples/core/Miscellaneous/ConfiguringDbContext/WebApp9/Program9.cs @@ -0,0 +1,40 @@ +var builder = WebApplication.CreateBuilder(args); +// +var connectionString = + builder.Configuration.GetConnectionString("DefaultConnection") + ?? throw new InvalidOperationException("Connection string" + + "'DefaultConnection' not found."); + +builder.Services.AddDbContext(options => + options.UseSqlServer(connectionString)); +// + +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) + .AddEntityFrameworkStores(); +builder.Services.AddRazorPages(); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.UseMigrationsEndPoint(); +} +else +{ + app.UseExceptionHandler("/Error"); + app.UseHsts(); +} + +app.UseHttpsRedirection(); + +app.UseRouting(); + +app.UseAuthorization(); + +app.MapStaticAssets(); +app.MapRazorPages() + .WithStaticAssets(); + +app.Run(); diff --git a/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/FactoryServicesExample.cs b/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/FactoryServicesExample.cs index 034058717a..c31dcf6616 100644 --- a/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/FactoryServicesExample.cs +++ b/samples/core/Miscellaneous/ConfiguringDbContext/WithContextFactory/FactoryServicesExample.cs @@ -10,8 +10,8 @@ public class FactoryServicesExample public void ConfigureServices(IServiceCollection services) { services.AddDbContextFactory( - options => - options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0")); + options => options.UseSqlServer( + @"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0")); } #endregion } diff --git a/samples/core/Miscellaneous/ConfiguringDbContext/WithNew/ApplicationDbContext.cs b/samples/core/Miscellaneous/ConfiguringDbContext/WithNew/ApplicationDbContext.cs index 70df3560a3..29e3b9c2f5 100644 --- a/samples/core/Miscellaneous/ConfiguringDbContext/WithNew/ApplicationDbContext.cs +++ b/samples/core/Miscellaneous/ConfiguringDbContext/WithNew/ApplicationDbContext.cs @@ -7,7 +7,8 @@ public class ApplicationDbContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0"); + optionsBuilder.UseSqlServer( + @"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0"); } } #endregion diff --git a/samples/core/Miscellaneous/NewInEFCore9/QuerySample.cs b/samples/core/Miscellaneous/NewInEFCore9/QuerySample.cs index aaadd10ff4..9937471d30 100644 --- a/samples/core/Miscellaneous/NewInEFCore9/QuerySample.cs +++ b/samples/core/Miscellaneous/NewInEFCore9/QuerySample.cs @@ -215,8 +215,7 @@ async Task> GetPostsForceConstantCollection(int[] ids) Console.WriteLine(); Console.WriteLine("Aggregate over subquery/aggregate:"); Console.WriteLine(); - - #region AggregateOverSubquery + // var latestPostsAverageRatingByLanguage = await context.Blogs. Select(x => new { @@ -226,7 +225,7 @@ async Task> GetPostsForceConstantCollection(int[] ids) .GroupBy(x => x.Language) .Select(x => x.Average(xx => xx.LatestPostRating)) .ToListAsync(); - #endregion + // // Max over decimal is not supported on Sqlite if (!context.UseSqlite)