From 57f6976efb82096d9f0d4bcce592df8f5afe97dc Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Sat, 3 Jun 2023 15:18:53 +0800 Subject: [PATCH] feat: DbContext --- Docs/学习总结.ipynb | 112 ++++++- Docs/说明.md | 59 +++- .../Pages/Index.razor | 28 ++ EFCore7Study.BlazorServerApp/Program.cs | 17 + EFCore7Study.BlazorServerApp/appsettings.json | 5 +- EFCore7Study.CoreConsoleApp/Program.cs | 309 +++--------------- EFCore7Study.DataService/AppDbContext.cs | 24 +- EFCore7Study.DataService/AppDbContext2.cs | 49 +++ EFCore7Study.DataService/AppDbContext3.cs | 58 ++++ EFCore7Study.DataService/Models/Account.cs | 6 +- .../Controllers/AccountsController.cs | 26 ++ .../Controllers/EFCore2Controller.cs | 43 +++ .../Controllers/EFCore3Controller.cs | 60 ++++ .../Controllers/EFCoreController.cs | 63 ++++ .../EFCore7Study.WebApi.csproj | 4 + EFCore7Study.WebApi/Program.cs | 131 +++++++- EFCore7Study.WebApi/appsettings.json | 5 +- 17 files changed, 713 insertions(+), 286 deletions(-) create mode 100644 EFCore7Study.DataService/AppDbContext2.cs create mode 100644 EFCore7Study.DataService/AppDbContext3.cs create mode 100644 EFCore7Study.WebApi/Controllers/AccountsController.cs create mode 100644 EFCore7Study.WebApi/Controllers/EFCore2Controller.cs create mode 100644 EFCore7Study.WebApi/Controllers/EFCore3Controller.cs create mode 100644 EFCore7Study.WebApi/Controllers/EFCoreController.cs diff --git a/Docs/学习总结.ipynb b/Docs/学习总结.ipynb index e73b1f3..c8f0e0b 100644 --- a/Docs/学习总结.ipynb +++ b/Docs/学习总结.ipynb @@ -19,7 +19,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -31,7 +31,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Restore sources
  • https://api.nuget.org/v3/index.json
Installed Packages
  • Microsoft.EntityFrameworkCore, 7.0.5
  • Microsoft.EntityFrameworkCore.InMemory, 7.0.5
  • Microsoft.EntityFrameworkCore.Sqlite, 7.0.5
  • Microsoft.EntityFrameworkCore.SqlServer, 7.0.5
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "//设置包源\n", "#i \"https://api.nuget.org/v3/index.json\"\n", @@ -50,6 +60,104 @@ "source": [ "## DbContext" ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + }, + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
indexvalue
0
Submission#6+Account
Id
1
Code001
Namezhangsan
Pwd123456
Age
25
State
0
1
Submission#6+Account
Id
2
Code002
Namelisi
Pwd123456
Age
35
State
0
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "using Microsoft.EntityFrameworkCore;\n", + "using Microsoft.EntityFrameworkCore.SqlServer;\n", + "public class AppDbContext: DbContext\n", + "{\n", + " public DbSet Accounts {get;set;}\n", + "\n", + " protected override void OnConfiguring(DbContextOptionsBuilder builder)\n", + " {\n", + " builder\n", + " .UseSqlServer(@\"Server=127.0.0.1\\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;\")\n", + " .EnableSensitiveDataLogging();\n", + " }\n", + "\n", + " protected override void OnModelCreating(ModelBuilder builder)\n", + " {\n", + " builder.Entity().ToTable(\"Account\");\n", + " base.OnModelCreating(builder);\n", + " }\n", + "}\n", + "\n", + "public class Account\n", + "{\n", + " public int Id { get; set; }\n", + " public string Code { get; set; }\n", + " public string Name { get; set; }\n", + " public string Pwd { get; set; }\n", + "\n", + " public int Age { get; set; }\n", + "\n", + " public int State { get; set; } \n", + "}\n", + "\n", + "using(var db = new AppDbContext())\n", + "{\n", + " var itmes = db.Accounts.ToList();\n", + "\n", + " itmes.Display();\n", + "\n", + "}" + ] } ], "metadata": { diff --git a/Docs/说明.md b/Docs/说明.md index 3b871e4..ce19423 100644 --- a/Docs/说明.md +++ b/Docs/说明.md @@ -1,3 +1,60 @@ # 说明 ======== -EF Core 7的学习总结项目。 \ No newline at end of file +EF Core 7的学习总结项目。 + +## 使用 工厂对象(AddDbContextFactory)时,多构建函数时,IoC获取对象时会异常 +在使用扩展方法 AddDbContextFactory()注册服务时,如果 DbContext有多个构建函数,会在获取服务时因为不知道使用哪个构建函数而异常。 + +解决方案: ++ 不要使用多构造函数 ++ 合并成一个构建函数:比如统一使用 DbContextOptions 参数,非IoC可以手动构建 DbContextOptions 对象当参数 ++ 使用 ActivatorUtilitiesConstructor 特性,指定IoC使用的构造函数 +```csharp +public class AppDbContext : DbContext + { + private string? _connectString; + + public AppDbContext() + { + + } + + public AppDbContext(string? connectstring, string dd = "dd") + { + _connectString = connectstring; + } + + //指定IoC使用的构造函数 + [ActivatorUtilitiesConstructor] + public AppDbContext(DbContextOptions options) + : base(options) + { + + } + + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { + if (string.IsNullOrWhiteSpace(_connectString)) + { + _connectString = @"Server=127.0.0.1\SQL2019;Database=EFCore7Study;User Id=sa;Password=xxxx;Encrypt=True;TrustServerCertificate=True;"; + } + + optionsBuilder + .UseSqlServer(_connectString) + .EnableSensitiveDataLogging(); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("Account"); + + base.OnModelCreating(modelBuilder); + } + + public DbSet Accounts { get; set; } + } +``` \ No newline at end of file diff --git a/EFCore7Study.BlazorServerApp/Pages/Index.razor b/EFCore7Study.BlazorServerApp/Pages/Index.razor index 6085c4a..4ab4055 100644 --- a/EFCore7Study.BlazorServerApp/Pages/Index.razor +++ b/EFCore7Study.BlazorServerApp/Pages/Index.razor @@ -1,9 +1,37 @@ @page "/" +@using EFCore7Study.DataService; +@using EFCore7Study.DataService.Models; +@using Microsoft.EntityFrameworkCore; +@inject IDbContextFactory DbFactory Index +@foreach(var account in AccountList) +{ +

@(account.Name)

+} +

Hello, world!

Welcome to your new app. + +@code{ + private List AccountList { get; set; } = new List(); + + protected override void OnInitialized() + { + AccountList = GetAccounts(); + base.OnInitialized(); + } + + private List GetAccounts() + { + using (var context = DbFactory.CreateDbContext()) + { + return context.Accounts.ToList(); + + }; + } +} diff --git a/EFCore7Study.BlazorServerApp/Program.cs b/EFCore7Study.BlazorServerApp/Program.cs index ada4af6..8283be9 100644 --- a/EFCore7Study.BlazorServerApp/Program.cs +++ b/EFCore7Study.BlazorServerApp/Program.cs @@ -1,7 +1,10 @@ using EFCore7Study.BlazorServerApp.Data; +using EFCore7Study.DataService; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Internal; namespace EFCore7Study.BlazorServerApp { @@ -16,6 +19,20 @@ namespace EFCore7Study.BlazorServerApp builder.Services.AddServerSideBlazor(); builder.Services.AddSingleton(); + //EF Core + var connectString = builder.Configuration.GetConnectionString("SQLServer"); + + + + + + builder.Services.AddDbContextFactory + ( + b => b.UseSqlServer(connectString).EnableSensitiveDataLogging(), ServiceLifetime.Scoped + ); + + builder.Services.AddDbContextFactory(options => options.UseSqlServer(connectString)); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/EFCore7Study.BlazorServerApp/appsettings.json b/EFCore7Study.BlazorServerApp/appsettings.json index 10f68b8..5ad2086 100644 --- a/EFCore7Study.BlazorServerApp/appsettings.json +++ b/EFCore7Study.BlazorServerApp/appsettings.json @@ -5,5 +5,8 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "SQLServer": "Server=127.0.0.1\\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;" + } } diff --git a/EFCore7Study.CoreConsoleApp/Program.cs b/EFCore7Study.CoreConsoleApp/Program.cs index 580f256..d71e6fb 100644 --- a/EFCore7Study.CoreConsoleApp/Program.cs +++ b/EFCore7Study.CoreConsoleApp/Program.cs @@ -8,274 +8,53 @@ namespace EFCore7Study.CoreConsoleApp { static void Main(string[] args) { - AnsiConsole.Status() - .Spinner(Spinner.Known.BouncingBar) - .Start("测试一个", ctx => - { - ctx.Spinner(Spinner.Known.BouncingBar); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Aesthetic)); - - ctx.Spinner(Spinner.Known.Arc); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Arc)); - - ctx.Spinner(Spinner.Known.Arrow); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Arrow)); - - ctx.Spinner(Spinner.Known.Arrow2); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Arrow2)); - - ctx.Spinner(Spinner.Known.Arrow3); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Arrow3)); - - ctx.Spinner(Spinner.Known.Balloon); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Balloon)); - - ctx.Spinner(Spinner.Known.Balloon2); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Balloon2)); - - ctx.Spinner(Spinner.Known.BetaWave); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.BetaWave)); - - ctx.Spinner(Spinner.Known.Bounce); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Bounce)); - - ctx.Spinner(Spinner.Known.BouncingBall); - Thread.Sleep(3000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.BouncingBall)); - - ctx.Spinner(Spinner.Known.BouncingBar); - Thread.Sleep(3000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.BouncingBar)); - - ctx.Spinner(Spinner.Known.BoxBounce); - Thread.Sleep(3000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.BoxBounce)); - - ctx.Spinner(Spinner.Known.BoxBounce2); - Thread.Sleep(3000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.BoxBounce2)); - - ctx.Spinner(Spinner.Known.Dots8Bit); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Dots8Bit)); - - ctx.Spinner(Spinner.Known.Christmas); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Christmas)); - - ctx.Spinner(Spinner.Known.Circle); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Circle)); - - ctx.Spinner(Spinner.Known.CircleHalves); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.CircleHalves)); - - ctx.Spinner(Spinner.Known.CircleQuarters); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.CircleQuarters)); - - ctx.Spinner(Spinner.Known.Clock); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Clock)); - - ctx.Spinner(Spinner.Known.Default); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Default)); - - ctx.Spinner(Spinner.Known.Dots); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Dots)); - - ctx.Spinner(Spinner.Known.Dots2); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Dots2)); - - ctx.Spinner(Spinner.Known.Dots8Bit); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Dots8Bit)); - //======================================================== - ctx.Spinner(Spinner.Known.Dqpb); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Dqpb)); - - ctx.Spinner(Spinner.Known.Earth); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Earth)); - - ctx.Spinner(Spinner.Known.Flip); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Flip)); - - ctx.Spinner(Spinner.Known.Grenade); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Grenade)); - - ctx.Spinner(Spinner.Known.GrowHorizontal); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.GrowHorizontal)); - - ctx.Spinner(Spinner.Known.GrowVertical); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.GrowVertical)); - - ctx.Spinner(Spinner.Known.Hamburger); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Hamburger)); - Thread.Sleep(2000); - - ctx.Spinner(Spinner.Known.Hearts); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Hearts)); - - ctx.Spinner(Spinner.Known.Layer); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Layer)); - - ctx.Spinner(Spinner.Known.Line); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Line)); - - ctx.Spinner(Spinner.Known.Line2); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Line2)); - - ctx.Spinner(Spinner.Known.Material); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Material)); - - ctx.Spinner(Spinner.Known.Monkey); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Monkey)); - - ctx.Spinner(Spinner.Known.Moon); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Moon)); - - ctx.Spinner(Spinner.Known.Noise); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Noise)); - - ctx.Spinner(Spinner.Known.Pipe); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Pipe)); - - ctx.Spinner(Spinner.Known.Point); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Dots8Bit)); - - ctx.Spinner(Spinner.Known.Pong); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Pong)); - - ctx.Spinner(Spinner.Known.Runner); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Runner)); - - ctx.Spinner(Spinner.Known.Shark); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Shark)); - - ctx.Spinner(Spinner.Known.SimpleDots); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.SimpleDots)); - - ctx.Spinner(Spinner.Known.SimpleDotsScrolling); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.SimpleDotsScrolling)); - - ctx.Spinner(Spinner.Known.Smiley); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Smiley)); - - ctx.Spinner(Spinner.Known.SquareCorners); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.SquareCorners)); - - ctx.Spinner(Spinner.Known.Squish); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Squish)); - - ctx.Spinner(Spinner.Known.Star); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Star)); - - ctx.Spinner(Spinner.Known.Star2); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Star2)); - - ctx.Spinner(Spinner.Known.Toggle); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Toggle)); - - ctx.Spinner(Spinner.Known.Toggle2); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Toggle2)); - - ctx.Spinner(Spinner.Known.Triangle); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Triangle)); - - ctx.Spinner(Spinner.Known.Weather); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Weather)); - - ctx.Spinner(Spinner.Known.Weather); - Thread.Sleep(2000); - AnsiConsole.MarkupLine(nameof(Spinner.Known.Weather)); - }); + } + static void ShowQuery() + { AnsiConsole.Status() - .Spinner(Spinner.Known.Balloon) - .Start("准备查询数据库...", ctx => - { - Thread.Sleep(2000); - - // 生成查询对象 - ctx.Status("生成查询对象..."); - AppDbContext dbContext = new AppDbContext(); - Thread.Sleep(2000); - AnsiConsole.MarkupLine("生成查询对象: DbContext, 完成!"); - - // 连接数据库 - ctx.Status("正在连接到数据库服务器..."); - ctx.Spinner(Spinner.Known.Balloon); - ctx.SpinnerStyle(Style.Parse("green")); - Thread.Sleep(2000); - AnsiConsole.MarkupLine("已连接到数据库服务器!"); - - - // 查询数据 - ctx.Status("正在查询数据..."); - ctx.Spinner(Spinner.Known.Star2); - ctx.SpinnerStyle(Style.Parse("yellow")); - Thread.Sleep(3000); - AnsiConsole.MarkupLine("完成查询!"); - - - //输出查询结果 - ctx.Status("输出查询结果..."); - ctx.Spinner(Spinner.Known.Arrow); - ctx.SpinnerStyle(Style.Parse("red")); - - dbContext.Accounts.ToList().ForEach(x => - { - AnsiConsole.MarkupLine($"标识:{x.Id},编号:{x.Code}, 姓名:{x.Name.PadRight(10)},年龄:{x.Age}, 密码:{x.Pwd}"); - Thread.Sleep(300); - }); - - AnsiConsole.MarkupLine("任务完成!"); - - }); + .Spinner(Spinner.Known.Balloon) + .Start("准备查询数据库...", ctx => + { + Thread.Sleep(2000); + + // 生成查询对象 + ctx.Status("生成查询对象..."); + AppDbContext dbContext = new AppDbContext(); + //Thread.Sleep(2000); + AnsiConsole.MarkupLine("生成查询对象: DbContext, 完成!"); + + // 连接数据库 + ctx.Status("正在连接到数据库服务器..."); + ctx.Spinner(Spinner.Known.Balloon); + ctx.SpinnerStyle(Style.Parse("green")); + //Thread.Sleep(2000); + AnsiConsole.MarkupLine("已连接到数据库服务器!"); + + + // 查询数据 + ctx.Status("正在查询数据..."); + ctx.Spinner(Spinner.Known.Star2); + ctx.SpinnerStyle(Style.Parse("yellow")); + //Thread.Sleep(3000); + AnsiConsole.MarkupLine("完成查询!"); + + + //输出查询结果 + ctx.Status("输出查询结果..."); + ctx.Spinner(Spinner.Known.Arrow); + ctx.SpinnerStyle(Style.Parse("red")); + + dbContext.Accounts.ToList().ForEach(x => + { + AnsiConsole.MarkupLine($"标识:{x.Id},编号:{x.Code}, 姓名:{x.Name.PadRight(10)},年龄:{x.Age}, 密码:{x.Pwd}"); + Thread.Sleep(300); + }); + + AnsiConsole.MarkupLine("任务完成!"); + + }); } } } \ No newline at end of file diff --git a/EFCore7Study.DataService/AppDbContext.cs b/EFCore7Study.DataService/AppDbContext.cs index 3fb0003..d1922ef 100644 --- a/EFCore7Study.DataService/AppDbContext.cs +++ b/EFCore7Study.DataService/AppDbContext.cs @@ -1,25 +1,27 @@ using EFCore7Study.DataService.Models; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace EFCore7Study.DataService { + /// + /// 多构造函数 + /// 为使用工厂方式注册,加 ActivatorUtilitiesConstructor 特性 + /// public class AppDbContext : DbContext { - private string? _connectString; + /// + /// 连接字符串,可实现属性设置,避免多构造函数在Factory时,IoC异常 + /// + public string? ConnectString = @"Server=127.0.0.1\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;"; public AppDbContext() { } - public AppDbContext(string connectstring) - { - _connectString = connectstring; - } - - public AppDbContext(DbContextOptions options) - : base(options) + public AppDbContext(DbContextOptions options) : base(options) { } @@ -28,13 +30,13 @@ namespace EFCore7Study.DataService { if (!optionsBuilder.IsConfigured) { - if (string.IsNullOrWhiteSpace(_connectString)) + if (string.IsNullOrWhiteSpace(ConnectString)) { - _connectString = @"Server=127.0.0.1\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;"; + ConnectString = @"Server=127.0.0.1\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;"; } optionsBuilder - .UseSqlServer(_connectString) + .UseSqlServer(ConnectString) .EnableSensitiveDataLogging(); } } diff --git a/EFCore7Study.DataService/AppDbContext2.cs b/EFCore7Study.DataService/AppDbContext2.cs new file mode 100644 index 0000000..21fc10a --- /dev/null +++ b/EFCore7Study.DataService/AppDbContext2.cs @@ -0,0 +1,49 @@ +using EFCore7Study.DataService.Models; + +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure.Internal; +using Microsoft.Extensions.DependencyInjection; + +namespace EFCore7Study.DataService +{ + /// + /// 多构造函数 + /// 为使用工厂方式注册,合并为一个 + /// + public class AppDbContext2 : DbContext + { + private string? _connectString; + + //因为先执行的 base(options),到此处时AppDbContext2已经注册完成,连接字符串实际上是用不了的。当然换成其它参数或用在其它地方是可以的。 + public AppDbContext2(DbContextOptions options, string? connectString = null) + : base(options) + { + _connectString = connectString; + } + + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { + if (string.IsNullOrWhiteSpace(_connectString)) + { + _connectString = @"Server=127.0.0.1\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;"; + } + + optionsBuilder + .UseSqlServer(_connectString) + .EnableSensitiveDataLogging(); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("Account"); + + base.OnModelCreating(modelBuilder); + } + + public DbSet Accounts { get; set; } + } +} \ No newline at end of file diff --git a/EFCore7Study.DataService/AppDbContext3.cs b/EFCore7Study.DataService/AppDbContext3.cs new file mode 100644 index 0000000..8eae800 --- /dev/null +++ b/EFCore7Study.DataService/AppDbContext3.cs @@ -0,0 +1,58 @@ +using EFCore7Study.DataService.Models; + +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace EFCore7Study.DataService +{ + /// + /// 多构造函数 + /// 使用工厂对象(AddDbContextFactory)时,因多构建函数,IoC 获取对象时会异常 + /// + public class AppDbContext3 : DbContext + { + private string? _connectString; + + public AppDbContext3() + { + + } + + public AppDbContext3(string? connectstring) + { + _connectString = connectstring; + } + + + public AppDbContext3(DbContextOptions options) + : base(options) + { + + } + + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { + if (string.IsNullOrWhiteSpace(_connectString)) + { + _connectString = @"Server=127.0.0.1\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;"; + } + + optionsBuilder + .UseSqlServer(_connectString) + .EnableSensitiveDataLogging(); + } + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("Account"); + + base.OnModelCreating(modelBuilder); + } + + public DbSet Accounts { get; set; } + } +} \ No newline at end of file diff --git a/EFCore7Study.DataService/Models/Account.cs b/EFCore7Study.DataService/Models/Account.cs index b8bc6a3..09557fa 100644 --- a/EFCore7Study.DataService/Models/Account.cs +++ b/EFCore7Study.DataService/Models/Account.cs @@ -6,9 +6,9 @@ public class Account { public int Id { get; set; } - public string Code { get; set; } - public string Name { get; set; } - public string Pwd { get; set; } + public string Code { get; set; } = ""; + public string Name { get; set; } = ""; + public string Pwd { get; set; } = ""; public int Age { get; set; } diff --git a/EFCore7Study.WebApi/Controllers/AccountsController.cs b/EFCore7Study.WebApi/Controllers/AccountsController.cs new file mode 100644 index 0000000..a6ad7e5 --- /dev/null +++ b/EFCore7Study.WebApi/Controllers/AccountsController.cs @@ -0,0 +1,26 @@ +using EFCore7Study.DataService; +using EFCore7Study.DataService.Models; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace EFCore7Study.WebApi.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class AccountsController : ControllerBase + { + private readonly AppDbContext _dbContext; + + public AccountsController(AppDbContext context) + { + _dbContext = context; + } + + [HttpGet] + public List AllAccounts() + { + return _dbContext.Accounts.ToList(); + } + } +} diff --git a/EFCore7Study.WebApi/Controllers/EFCore2Controller.cs b/EFCore7Study.WebApi/Controllers/EFCore2Controller.cs new file mode 100644 index 0000000..eeb1020 --- /dev/null +++ b/EFCore7Study.WebApi/Controllers/EFCore2Controller.cs @@ -0,0 +1,43 @@ +using EFCore7Study.DataService; +using EFCore7Study.DataService.Models; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Internal; + +namespace EFCore7Study.WebApi.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class EFCore2Controller : ControllerBase + { + private readonly AppDbContext2 _context; + private readonly IDbContextFactory _factory; + + public EFCore2Controller + ( + AppDbContext2 context, + IDbContextFactory factory + ) + { + _context = context; + _factory = factory; + } + + [HttpGet] + public List GetAll() + { + return _context.Accounts.AsNoTracking().ToList(); + } + + [HttpGet] + public List GetAllByFactory() + { + using (var db = _factory.CreateDbContext()) + { + return db.Accounts.AsNoTracking().ToList(); + } + } + } +} diff --git a/EFCore7Study.WebApi/Controllers/EFCore3Controller.cs b/EFCore7Study.WebApi/Controllers/EFCore3Controller.cs new file mode 100644 index 0000000..be18a9d --- /dev/null +++ b/EFCore7Study.WebApi/Controllers/EFCore3Controller.cs @@ -0,0 +1,60 @@ +using EFCore7Study.DataService; +using EFCore7Study.DataService.Models; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Internal; + +namespace EFCore7Study.WebApi.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class EFCore3Controller : ControllerBase + { + + private readonly IDbContextFactory _contextFactory; + + public EFCore3Controller(IDbContextFactory contextFactory) + { + _contextFactory = contextFactory; + } + + + [HttpGet] + public List GetAll() + { + return _contextFactory.CreateDbContext().Accounts.ToList(); + } + + [HttpGet] + public List GetAll2() + { + return _contextFactory.CreateDbContext().Accounts.ToList(); + } + + [HttpGet] + public List GetAll3() + { + return _contextFactory.CreateDbContext().Accounts.ToList(); + } + + [HttpGet] + public List GetAll4() + { + return _contextFactory.CreateDbContext().Accounts.ToList(); + } + + [HttpGet] + public List GetAll5() + { + return _contextFactory.CreateDbContext().Accounts.ToList(); + } + + [HttpGet] + public List GetAll6() + { + return _contextFactory.CreateDbContext().Accounts.ToList(); + } + } +} diff --git a/EFCore7Study.WebApi/Controllers/EFCoreController.cs b/EFCore7Study.WebApi/Controllers/EFCoreController.cs new file mode 100644 index 0000000..71a7989 --- /dev/null +++ b/EFCore7Study.WebApi/Controllers/EFCoreController.cs @@ -0,0 +1,63 @@ +using EFCore7Study.DataService; +using EFCore7Study.DataService.Models; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace EFCore7Study.WebApi.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class EFCoreController : ControllerBase + { + private readonly AppDbContext _connect; + private readonly IDbContextFactory _factory; + + public EFCoreController(AppDbContext context, IDbContextFactory factory) + { + _connect = context; + _factory = factory; + } + + + [HttpGet] + public List GetAll() + { + return _connect.Accounts.ToList(); + } + + [HttpGet] + public List GetAllByFactory() + { + using (var db = _factory.CreateDbContext()) + { + return db.Accounts.ToList(); + } + } + + [HttpGet] + public List GetAll3() + { + return _connect.Accounts.ToList(); + } + + [HttpGet] + public List GetAll4() + { + return _connect.Accounts.ToList(); + } + + [HttpGet] + public List GetAll5() + { + return _connect.Accounts.ToList(); + } + + [HttpGet] + public List GetAll6() + { + return _connect.Accounts.ToList(); + } + } +} diff --git a/EFCore7Study.WebApi/EFCore7Study.WebApi.csproj b/EFCore7Study.WebApi/EFCore7Study.WebApi.csproj index d6f9db3..7fbf2db 100644 --- a/EFCore7Study.WebApi/EFCore7Study.WebApi.csproj +++ b/EFCore7Study.WebApi/EFCore7Study.WebApi.csproj @@ -12,4 +12,8 @@ + + + + diff --git a/EFCore7Study.WebApi/Program.cs b/EFCore7Study.WebApi/Program.cs index 2cc1c2d..137f58e 100644 --- a/EFCore7Study.WebApi/Program.cs +++ b/EFCore7Study.WebApi/Program.cs @@ -1,3 +1,7 @@ +using EFCore7Study.DataService; + +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.SqlServer; namespace EFCore7Study.WebApi { @@ -14,9 +18,132 @@ namespace EFCore7Study.WebApi builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); - var app = builder.Build(); + //注册服务:EFCore + #region 注册服务:EFCore + var connectString = builder.Configuration.GetConnectionString("SQLServer"); + var contextOptionsBuilder = new DbContextOptionsBuilder() + .UseSqlServer(connectString) + .EnableSensitiveDataLogging(); + var contextOptions = contextOptionsBuilder.Options; + + //方式一:默认构造,使用内部数据连接 + //builder.Services.AddScoped(provider => new AppDbContext()); + + //方式二: 设置连接字符串属性 + //builder.Services.AddScoped(provider => + //{ + // var db = new AppDbContext(); + // db.ConnectString = connectString; + // return db; + //}); + + //方法三:使用 DbContextOptions 的构建函数 [比较推荐] + //builder.Services.AddScoped(provider => new AppDbContext(contextOptions)); + + //方式四:使用 AddDbContext 扩展方法 [官方推荐] + //小问题:会覆盖之前方法的服务注册,猜测内部进行过去重复处理过,要验证请使用 GetServices 获取所有注册的服务。 + //解决:方法三放在方法四后面 + //builder.Services.AddDbContext(option => + //{ + // //从配置中获取连接字符串 + // option.UseSqlServer(connectString) + // .EnableSensitiveDataLogging(); + //}); + + //方式五: 使用 DbContextFactory 工厂 + //注意: + // 1、此方法与方法四都是注册的 AppDbContext对象,方法四默认为Scoped,此方式默认为单例,两者的冲突导致异常 + // 2、此方法与方法四,都会覆盖之前的 AppDbContext 注册 + //解决: + // 1、此方法不与方法4同用,如果要同时使用,请使用方法1-3 + // 2、使此方法与方法四,应用相同生命周期 + //builder.Services.AddDbContextFactory(optionBuilder => + //{ + // optionBuilder.UseSqlServer(connectString) + // .EnableSensitiveDataLogging(); + //}); + + //使用自定的覆盖工厂的AppDbContext,但工厂本身的IDbContextFactory不会覆盖,可以分开使用。 + //builder.Services.AddScoped(provider => new AppDbContext(contextOptions)); + + //方式六:使用 DbContextPool 池 + builder.Services.AddDbContextPool((provider, optionBuilder) => + { + //provider.GetRequiredService(); + optionBuilder.UseSqlServer(connectString) + .EnableSensitiveDataLogging(); + }, poolSize: 2048); + + //方式七:使用连接池的工厂 + builder.Services.AddPooledDbContextFactory((serviceProvider, optionBuilder) => + { + //serviceProvider.GetRequiredService(); + + optionBuilder.UseSqlServer(connectString) + .EnableSensitiveDataLogging(); + }, poolSize: 1024); + + //使用自定的覆盖工厂的AppDbContext,但工厂本身的IDbContextFactory不会覆盖,可以分开使用。 + builder.Services.AddScoped(provider => new AppDbContext()); + + //获取所有注册的服务(可没查看是否覆盖注册) + //var dd = builder?.Services?.BuildServiceProvider().GetServices(); + #endregion + + #region 注册服务:EFCore2 + + var contextOptionBuilder2 = new DbContextOptionsBuilder() + .UseSqlServer(connectString) + .EnableSensitiveDataLogging(); + DbContextOptions? contextOptions2 = contextOptionBuilder2.Options; + + //方法:使用 统一构建函数 + //builder.Services.AddScoped(provider => new AppDbContext2(contextOptions)); + //或者 + builder?.Services.AddScoped(provider => new AppDbContext2(contextOptions2, connectString)); + + //方式:使用 AddDbContext 扩展方法 [官方推荐] + //builder.Services.AddDbContext((server, option) => + //{ + // //从配置中获取连接字符串 + // //builder.Configuration.GetConnectionString("SQLServer"); + + // //设置 + // option.UseSqlServer(connectString) + // .EnableSensitiveDataLogging(); + //}); + + //方式: 使用 DbContextFactory 工厂 + //builder.Services.AddDbContextFactory(optionBuilder => + //{ + // optionBuilder.UseSqlServer(connectString) + // .EnableSensitiveDataLogging(); + //}, ServiceLifetime.Scoped); + + //或者 + //builder.Services.AddDbContextFactory((provider, builder) => + //{ + + + //}, ServiceLifetime.Scoped); + + //方式:使用 DbContextPool 池 + //builder.Services.AddDbContextPool(optionBuilder => + //{ + // optionBuilder.UseSqlServer(connectString) + // .EnableSensitiveDataLogging(); + //}); + + //方式:使用连接池的工厂 + //builder.Services.AddPooledDbContextFactory(optionBuilder => + //{ + // optionBuilder.UseSqlServer(connectString) + // .EnableSensitiveDataLogging(); + //}); + #endregion + + var app = builder!.Build(); - // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); diff --git a/EFCore7Study.WebApi/appsettings.json b/EFCore7Study.WebApi/appsettings.json index 10f68b8..5ad2086 100644 --- a/EFCore7Study.WebApi/appsettings.json +++ b/EFCore7Study.WebApi/appsettings.json @@ -5,5 +5,8 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "SQLServer": "Server=127.0.0.1\\SQL2019;Database=EFCore7Study;User Id=sa;Password=gly-bicijinlian;Encrypt=True;TrustServerCertificate=True;" + } }