在.NET Core中使用Entity Framework与在.NET Framework中使用有一个小小的不同,在前者中没有后者中可用的图形化配置界面Entity Framework Designer(EF设计器)可用,故它只能通过命令行的方式进行配置,这里详细记录了在.NET Core中使用EF的一个具体示例,使用C#,.NET 7以及SQL Server。
-
安装各种NuGet包
Microsoft.EntityFramworkCore
Microsoft.EntityFramworkCore.Design
Microsoft.EntityFramworkCore.SqlServer
Microsoft.EntityFramworkCore.Tools -
根据数据库建立模型
使用Scaffold-DbContext命令,这个命令包含在上面的Microsoft.EntityFramworkCore.Tools里,如果在运行时提示没有这个命令,需要安装Microsoft.EntityFramworkCore.Tools(命令:Install-Package Microsoft.EntityFrameworkCore.Tools)。
在NuGet包管理器控制台里运行下面格式的命令:
Scaffold-DbContext <连接字符串> <数字库提供程序> -OutputDir <输出目录>
示例:
Scaffold-DbContext "Server=192.168.1.21;Database=InfoStore;User Id=InfoManager;Password=11111111;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
以上命令运行的时候可能不会成功,它会显示一个错误“A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)”,它是由于SQL Server使用的SSL证书不被客户端信任导致的。解决的办法一个是使用受信用的证书,另一个是将该证书添加到受信任的根证书颁发机构存储;第三个方法比较直接:在连接字符串设置信任服务器证书(添加TrustServerCertificate=True),或者直接放弃加密(清加Encrpt=False)。第三个方法是最快捷的方法但并不推荐,因为这会降低安全性。
Scaffold-DbContext "Server=192.168.1.21;Database=InfoStore;User Id=InfoManager;Password=11111111;TrustServerCertificate=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
(注意:使用上面的命令需注意输出目录的切换,这个Models指的当前目录下的Models,可以用命令DIR确认当前目录,也可以用命令CD来改变当前目录。)
命令运行成功后,指定的目录里就出现了指定数据库里所有数据表对应的模型文件,以及一个数据库上下文类,以数据库名字+“Context”为文件名,比如上面的生成的文件名是“InfoStoreContext.cs”。
图1. 新建立成功的数据库上下文类
如果在数据库更新后需要更新数据库模型,再次运行上面建立模型的命令即可,甚至后面可以带参数“-Force”或者“-f”进行强制更新。
如果只想更新特定的表,使用-t参数指定要更新的表即可,示例如下:
Scaffold-DbContext <连接字符串> <数字库提供程序> -OutputDir <输出目录> -t 表1 -t 表2 -t 表3
-
将数据库连接字串放到配置文件里
默认状态下连接字符串保存在上述的数据库上下文中,为了安全我们应该将它保存到配置文件中(保存到配置文件中后,如果可能,建议把数字库上下文类中的相关连接字符串删除,以策万全),步骤如下:
在配置文件中写入连接字符串(键名“DefaultConnection”可根据实际需要变更):
"ConnectionStrings": {
"DefaultConnection": "Server=192.168.1.21;Database=InfoStore;User Id=InfoManager;Password=11111111;TrustServerCertificate=True;"
},
图2. 将连接字串放到配置文件appsettings.json里
在Programs.cs的入口中创建服务(注意里面配置文件中的键名“DefaultConnection”要跟配置文件中的对应;同时创建服务的语句必须在“var app=builder.Build();”这一句的前面):
// Add services to the container.
builder.Services.AddDbContext<InfoStoreContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
图3. 在Program.cs中配置示例,注意红圈中内容所在的位置
接下来需要打开数据库上下文类的文件,找到
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)所在的位置,把这几行注释掉以使我们配置到配置文件中的数据库连接字符串生效。如下图所示:
图4. 注释掉红框中的行以使在配置文件中的数据库连接字符串生效
-
访问数据的方法
可以通过依赖注入(Dependency Injection)来获取DbContext的实例。
-
在类中注入DbContext:在类中,添加一个接收
DbContext参数的构造函数,并将DbContext保存为一个字段。例如:
public class MyClass
{
private readonly MyContext _context;
public MyClass(MyContext context)
{
_context = context;
}
// ...
}
-
使用DbContext:现在,可以在类的方法中使用
_context字段来访问数据库。例如:
public void DoSomething()
{
var blogs = _context.Blogs.ToList();
// Do something with the blogs...
}
这个例子中,DoSomething方法获取所有的博客并对它们进行处理。
-
注册类:最后,需要在
Program.cs文件中使用AddScoped,AddSingleton, 或AddTransient方法将您的类添加到服务容器。例如:
builder.Services.AddScoped<MyClass>();
需要注意的是在ASP.NET Core中,控制器是特殊的类,它们由ASP.NET Core的内置依赖注入系统自动处理。当一个HTTP请求到达并映射到一个控制器的动作方法时,ASP.NET Core会自动实例化该控制器,并注入所有在构造函数中声明的依赖项,包括DbContext,所以上面的第3步不需要,只需要第1步就可以了:
控制器中,添加一个接收DbContext参数的构造函数,并将DbContext保存为一个字段。
public class MyController: Controller
{
private readonly MyContext _context;
public MyController(MyContext context)
{
_context = context;
}
// ...
}
public IActionResult Index()
{
var blogs = _context.Blogs.ToList();
return View(blogs);
}
补充:对于需要使用多个注入参数的控制器,可以使用这样的方法(下面例子里对变量特意用的属性的写法,提供一种新的写法而已):
public class AuthenticateController : Controller
{
//这里也可以这样定义,不需要用属性的方式。比如:
//public readonly InfoStoreContext InfoStoreContext;
//public readonly IConfiguration Configuration;
public InfoStoreContext InfoStoreContext { get; }
public IConfiguration Configuration { get; }
public AuthenticateController(IConfiguration configuration, InfoStoreContext context)
{
Configuration = configuration;
InfoStoreContext = context;
}
}











网友评论