Skip to content

Commit a2ba0cf

Browse files
committed
Document design-time services
1 parent b26fccc commit a2ba0cf

File tree

11 files changed

+168
-31
lines changed

11 files changed

+168
-31
lines changed

entity-framework/core/miscellaneous/cli/dbcontext-creation.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ If your startup project uses the [ASP.NET Core Web Host][3] or [.NET Core Generi
1717

1818
The tools first try to obtain the service provider by invoking `Program.CreateHostBuilder()`, calling `Build()`, then accessing the `Services` property.
1919

20-
[!code-csharp[Main](../../../../samples/core/Miscellaneous/CommandLine/ApplicationService.cs)]
20+
[!code-csharp[Main](../../../../samples/core/Miscellaneous/CommandLine/ApplicationService.cs#ApplicationService)]
2121

2222
> [!NOTE]
2323
> When you create a new ASP.NET Core application, this hook is included by default.
@@ -32,7 +32,7 @@ If the DbContext can't be obtained from the application service provider, the to
3232

3333
You can also tell the tools how to create your DbContext by implementing the `IDesignTimeDbContextFactory<TContext>` interface: If a class implementing this interface is found in either the same project as the derived `DbContext` or in the application's startup project, the tools bypass the other ways of creating the DbContext and use the design-time factory instead.
3434

35-
[!code-csharp[Main](../../../../samples/core/Miscellaneous/CommandLine/BloggingContextFactory.cs)]
35+
[!code-csharp[Main](../../../../samples/core/Miscellaneous/CommandLine/BloggingContextFactory.cs#BloggingContextFactory)]
3636

3737
> [!NOTE]
3838
> Prior to EFCore 5.0 the `args` parameter was unused (see [this issue][8]).

entity-framework/core/miscellaneous/cli/services.md

+42-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,51 @@
22
title: Design-time services - EF Core
33
description: Information on Entity Framework Core design-time services
44
author: bricelam
5-
ms.date: 10/26/2017
5+
ms.date: 10/22/2020
66
uid: core/miscellaneous/cli/services
77
---
88
# Design-time services
99

1010
Some services used by the tools are only used at design time. These services are managed separately from EF Core's runtime services to prevent them from being deployed with your app. To override one of these services (for example the service to generate migration files), add an implementation of `IDesignTimeServices` to your startup project.
1111

12-
[!code-csharp[Main](../../../../samples/core/Miscellaneous/CommandLine/DesignTimeServices.cs)]
12+
[!code-csharp[Main](../../../../samples/core/Miscellaneous/CommandLine/DesignTimeServices.cs#DesignTimeServices)]
13+
14+
## Referencing Microsoft.EntityFrameworkCore.Design
15+
16+
Microsoft.EntityFrameworkCore.Design is a DevelopmentDependency package. This means that the dependency won't flow transitively into other projects, and that you cannot, by default, reference its types.
17+
18+
In order to reference its types and override design-time services, update the PackageReference item's metadata in your project file.
19+
20+
```xml
21+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.9">
22+
<PrivateAssets>all</PrivateAssets>
23+
<!-- Remove IncludeAssets to allow compiling against the assembly -->
24+
<!--<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
25+
</PackageReference>
26+
```
27+
28+
If the package is being referenced transitively via Microsoft.EntityFrameworkCore.Tools, you will need to add an explicit PackageReference to the package and change its metadata.
29+
30+
## List of services
31+
32+
The following is a list of the design-time services.
33+
34+
Service | Description
35+
------------------------------------------------------------------------------------ | -----------
36+
<xref:Microsoft.EntityFrameworkCore.Design.IAnnotationCodeGenerator> | Generates the code for corresponding model annotations.
37+
<xref:Microsoft.EntityFrameworkCore.Design.ICSharpHelper> | Helps with generating C# code.
38+
<xref:Microsoft.EntityFrameworkCore.Design.IPluralizer> | Pluralizes and singularizes words.
39+
<xref:Microsoft.EntityFrameworkCore.Migrations.Design.IMigrationsCodeGenerator> | Generates code for a migration.
40+
<xref:Microsoft.EntityFrameworkCore.Migrations.Design.IMigrationsScaffolder> | The main class for managing migration files.
41+
<xref:Microsoft.EntityFrameworkCore.Scaffolding.IDatabaseModelFactory> | Creates a database model from a database.
42+
<xref:Microsoft.EntityFrameworkCore.Scaffolding.IModelCodeGenerator> | Generates code for a model.
43+
<xref:Microsoft.EntityFrameworkCore.Scaffolding.IProviderConfigurationCodeGenerator> | Generates OnConfiguring code.
44+
<xref:Microsoft.EntityFrameworkCore.Scaffolding.IReverseEngineerScaffolder> | The main class for scaffolding reverse engineered models.
45+
46+
## Using services
47+
48+
These services can also be useful for creating your own tools. For example, when you want to automate part of you design-time workflow.
49+
50+
You can build a service provider containing these services using the AddEntityFrameworkDesignTimeServices and AddDbContextDesignTimeServices extension methods.
51+
52+
[!code-csharp[](../../../../samples/core/Miscellaneous/CommandLine/CustomTools.cs#CustomTools)]

samples/core/Miscellaneous/CommandLine/ApplicationService.cs

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
using Microsoft.AspNetCore.Hosting;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.Hosting;
5+
6+
#region ApplicationService
17
public class Program
28
{
39
public static void Main(string[] args)
@@ -23,3 +29,4 @@ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
2329
{
2430
}
2531
}
32+
#endregion

samples/core/Miscellaneous/CommandLine/BloggingContextFactory.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using Microsoft.EntityFrameworkCore;
22
using Microsoft.EntityFrameworkCore.Design;
3-
using Microsoft.EntityFrameworkCore.Infrastructure;
43

54
namespace MyProject
65
{
6+
#region BloggingContextFactory
77
public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
88
{
99
public BloggingContext CreateDbContext(string[] args)
@@ -14,4 +14,13 @@ public BloggingContext CreateDbContext(string[] args)
1414
return new BloggingContext(optionsBuilder.Options);
1515
}
1616
}
17+
#endregion
18+
19+
public class BloggingContext : DbContext
20+
{
21+
public BloggingContext(DbContextOptions<BloggingContext> options)
22+
: base(options)
23+
{
24+
}
25+
}
1726
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.9" />
9+
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.9" PrivateAssets="all" />
10+
</ItemGroup>
11+
12+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.IO;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.EntityFrameworkCore.Design;
4+
using Microsoft.EntityFrameworkCore.Migrations.Design;
5+
using Microsoft.Extensions.DependencyInjection;
6+
7+
namespace CommandLine
8+
{
9+
public class CustomTools
10+
{
11+
public static void AddMigration(string migrationName)
12+
{
13+
var projectDir = Directory.GetCurrentDirectory();
14+
var rootNamespace = "ConsoleApp1";
15+
var outputDir = "Migraitons";
16+
17+
#region CustomTools
18+
var db = new MyDbContext();
19+
20+
// Create design-time services
21+
var serviceCollection = new ServiceCollection();
22+
serviceCollection.AddEntityFrameworkDesignTimeServices();
23+
serviceCollection.AddDbContextDesignTimeServices(db);
24+
var serviceProvider = serviceCollection.BuildServiceProvider();
25+
26+
// Add a migration
27+
var migrationsScaffolder = serviceProvider.GetService<IMigrationsScaffolder>();
28+
var migration = migrationsScaffolder.ScaffoldMigration(migrationName, rootNamespace);
29+
migrationsScaffolder.Save(projectDir, migration, outputDir);
30+
#endregion
31+
}
32+
}
33+
34+
class MyDbContext : DbContext
35+
{
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
1+
using Microsoft.EntityFrameworkCore.Design;
2+
using Microsoft.EntityFrameworkCore.Migrations.Design;
3+
using Microsoft.Extensions.DependencyInjection;
4+
5+
#region DesignTimeServices
16
class MyDesignTimeServices : IDesignTimeServices
27
{
38
public void ConfigureDesignTimeServices(IServiceCollection services)
49
=> services.AddSingleton<IMigrationsCodeGenerator, MyMigrationsCodeGenerator>();
510
}
11+
#endregion
12+
13+
class MyMigrationsCodeGenerator : CSharpMigrationsGenerator
14+
{
15+
public MyMigrationsCodeGenerator(
16+
MigrationsCodeGeneratorDependencies dependencies,
17+
CSharpMigrationsGeneratorDependencies csharpDependencies)
18+
: base(dependencies, csharpDependencies)
19+
{
20+
}
21+
}

samples/core/Samples.sln

+20-22
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QueryFilters", "Querying\Qu
8383
EndProject
8484
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RelatedData", "Querying\RelatedData\RelatedData.csproj", "{CE9050E2-48AE-4CC4-8CCB-E19EE3102C0A}"
8585
EndProject
86-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleLogging", "Miscellaneous\Logging\SimpleLogging\SimpleLogging.csproj", "{6A67BD7F-86AA-4F18-ACAF-0420482189AE}"
86+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleLogging", "Miscellaneous\Logging\SimpleLogging\SimpleLogging.csproj", "{6A67BD7F-86AA-4F18-ACAF-0420482189AE}"
8787
EndProject
88-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompiledQueries", "CompiledQueries\CompiledQueries.csproj", "{077C2862-467F-4DE0-8412-0F0670C36593}"
88+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompiledQueries", "CompiledQueries\CompiledQueries.csproj", "{077C2862-467F-4DE0-8412-0F0670C36593}"
8989
EndProject
90-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Intro", "Intro\Intro.csproj", "{937D4D99-A6FE-459A-A5B8-A96D5D952D42}"
90+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Intro", "Intro\Intro.csproj", "{937D4D99-A6FE-459A-A5B8-A96D5D952D42}"
9191
EndProject
92-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NullableReferenceTypes", "Miscellaneous\NullableReferenceTypes\NullableReferenceTypes.csproj", "{0F8779BE-F32A-42A9-B2D7-1974A1D9DD09}"
92+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NullableReferenceTypes", "Miscellaneous\NullableReferenceTypes\NullableReferenceTypes.csproj", "{0F8779BE-F32A-42A9-B2D7-1974A1D9DD09}"
93+
EndProject
94+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommandLine", "Miscellaneous\CommandLine\CommandLine.csproj", "{EE7AF867-1BC6-4C80-8856-B4DDB975E546}"
95+
EndProject
96+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Schemas", "Schemas", "{0BFEC418-1A37-4960-8488-EA8AFB916EB9}"
97+
EndProject
98+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Migrations", "Schemas\Migrations\Migrations.csproj", "{D381F3EE-FEA4-4777-B9CA-7EE7E4C3289E}"
9399
EndProject
94100
Global
95101
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -233,28 +239,10 @@ Global
233239
{CE9050E2-48AE-4CC4-8CCB-E19EE3102C0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
234240
{CE9050E2-48AE-4CC4-8CCB-E19EE3102C0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
235241
{CE9050E2-48AE-4CC4-8CCB-E19EE3102C0A}.Release|Any CPU.Build.0 = Release|Any CPU
236-
{70E581C3-38BB-46CC-9063-ADF9F2B76570}.Release|ARM.ActiveCfg = Release|Any CPU
237-
{70E581C3-38BB-46CC-9063-ADF9F2B76570}.Release|ARM.Build.0 = Release|Any CPU
238-
{70E581C3-38BB-46CC-9063-ADF9F2B76570}.Release|x64.ActiveCfg = Release|Any CPU
239-
{70E581C3-38BB-46CC-9063-ADF9F2B76570}.Release|x64.Build.0 = Release|Any CPU
240-
{70E581C3-38BB-46CC-9063-ADF9F2B76570}.Release|x86.ActiveCfg = Release|Any CPU
241-
{70E581C3-38BB-46CC-9063-ADF9F2B76570}.Release|x86.Build.0 = Release|Any CPU
242242
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
243243
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
244-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|ARM.ActiveCfg = Debug|Any CPU
245-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|ARM.Build.0 = Debug|Any CPU
246-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|x64.ActiveCfg = Debug|Any CPU
247-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|x64.Build.0 = Debug|Any CPU
248-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|x86.ActiveCfg = Debug|Any CPU
249-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Debug|x86.Build.0 = Debug|Any CPU
250244
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
251245
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|Any CPU.Build.0 = Release|Any CPU
252-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|ARM.ActiveCfg = Release|Any CPU
253-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|ARM.Build.0 = Release|Any CPU
254-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|x64.ActiveCfg = Release|Any CPU
255-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|x64.Build.0 = Release|Any CPU
256-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|x86.ActiveCfg = Release|Any CPU
257-
{6A67BD7F-86AA-4F18-ACAF-0420482189AE}.Release|x86.Build.0 = Release|Any CPU
258246
{077C2862-467F-4DE0-8412-0F0670C36593}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
259247
{077C2862-467F-4DE0-8412-0F0670C36593}.Debug|Any CPU.Build.0 = Debug|Any CPU
260248
{077C2862-467F-4DE0-8412-0F0670C36593}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -267,6 +255,14 @@ Global
267255
{0F8779BE-F32A-42A9-B2D7-1974A1D9DD09}.Debug|Any CPU.Build.0 = Debug|Any CPU
268256
{0F8779BE-F32A-42A9-B2D7-1974A1D9DD09}.Release|Any CPU.ActiveCfg = Release|Any CPU
269257
{0F8779BE-F32A-42A9-B2D7-1974A1D9DD09}.Release|Any CPU.Build.0 = Release|Any CPU
258+
{EE7AF867-1BC6-4C80-8856-B4DDB975E546}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
259+
{EE7AF867-1BC6-4C80-8856-B4DDB975E546}.Debug|Any CPU.Build.0 = Debug|Any CPU
260+
{EE7AF867-1BC6-4C80-8856-B4DDB975E546}.Release|Any CPU.ActiveCfg = Release|Any CPU
261+
{EE7AF867-1BC6-4C80-8856-B4DDB975E546}.Release|Any CPU.Build.0 = Release|Any CPU
262+
{D381F3EE-FEA4-4777-B9CA-7EE7E4C3289E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
263+
{D381F3EE-FEA4-4777-B9CA-7EE7E4C3289E}.Debug|Any CPU.Build.0 = Debug|Any CPU
264+
{D381F3EE-FEA4-4777-B9CA-7EE7E4C3289E}.Release|Any CPU.ActiveCfg = Release|Any CPU
265+
{D381F3EE-FEA4-4777-B9CA-7EE7E4C3289E}.Release|Any CPU.Build.0 = Release|Any CPU
270266
EndGlobalSection
271267
GlobalSection(SolutionProperties) = preSolution
272268
HideSolutionNode = FALSE
@@ -304,6 +300,8 @@ Global
304300
{CE9050E2-48AE-4CC4-8CCB-E19EE3102C0A} = {1AD64707-0BE0-48B0-A803-916FF96DCB4F}
305301
{6A67BD7F-86AA-4F18-ACAF-0420482189AE} = {85AFD7F1-6943-40FE-B8EC-AA9DBB42CCA6}
306302
{0F8779BE-F32A-42A9-B2D7-1974A1D9DD09} = {85AFD7F1-6943-40FE-B8EC-AA9DBB42CCA6}
303+
{EE7AF867-1BC6-4C80-8856-B4DDB975E546} = {85AFD7F1-6943-40FE-B8EC-AA9DBB42CCA6}
304+
{D381F3EE-FEA4-4777-B9CA-7EE7E4C3289E} = {0BFEC418-1A37-4960-8488-EA8AFB916EB9}
307305
EndGlobalSection
308306
GlobalSection(ExtensibilityGlobals) = postSolution
309307
SolutionGuid = {20C98D35-54EF-46A6-8F3B-1855C1AE4F70}

samples/core/Schemas/Migrations/MigrationTableNameContext.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
using Microsoft.EntityFrameworkCore;
2-
using System.Collections.Generic;
32

43
namespace Migrations
54
{
65
public class MigrationTableNameContext : DbContext
76
{
7+
readonly string _connectionString = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Sample";
8+
89
#region TableNameContext
910
protected override void OnConfiguring(DbContextOptionsBuilder options)
1011
=> options.UseSqlServer(
11-
connectionString,
12+
_connectionString,
1213
x => x.MigrationsHistoryTable("__MyMigrationsHistory", "mySchema"));
1314
#endregion
1415
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.9" />
9+
</ItemGroup>
10+
11+
</Project>

samples/core/Schemas/Migrations/MyHistoryRepository.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
using Microsoft.EntityFrameworkCore;
2-
using System.Collections.Generic;
2+
using Microsoft.EntityFrameworkCore.Metadata.Builders;
3+
using Microsoft.EntityFrameworkCore.Migrations;
4+
using Microsoft.EntityFrameworkCore.SqlServer.Migrations.Internal;
5+
6+
#pragma warning disable EF1001
37

48
namespace Migrations
59
{
610
public class MyHistoryRepositoryContext : DbContext
711
{
12+
readonly string _connectionString = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Sample";
13+
814
#region HistoryRepositoryContext
915
protected override void OnConfiguring(DbContextOptionsBuilder options)
1016
=> options
11-
.UseSqlServer(connectionString)
17+
.UseSqlServer(_connectionString)
1218
.ReplaceService<IHistoryRepository, MyHistoryRepository>();
1319
#endregion
1420
}

0 commit comments

Comments
 (0)