在ASP.NET 4.x中(包括ASP.NET MVC 5),可以通过附加数据库文件的方式,将数据库保存在项目的文件中。这种方式对于不同时段需要更换计算机(白天办公室,晚上家里)开发时带来好处。
而.NET Core版本(包括 ASP.NET Core MVC )数据库是默认保存在c:/users/{username}中。
一、对于ASP.NET 4.x,本来项目文件默认存在着App_Data的系统文件夹,用来存放数据库文件。
数据库连接字符串中的|DataDirectory| 表示了App_Data文件。典型的连接字符串为:
<add name="MVCMovieContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\MVCMovieContext.mdf;Initial Catalog=MVCMovieContext;Integrated Security=True" providerName="System.Data.SqlClient" />
ASP.NET 4.X中的webconfig.config文件中, 数据库连接连接字符串中的 \ 符号已自动转义,不需要额外的双斜杠\\
二、对于ASP.NET Core程序,我们一般将数据库连接字符串保存在 appsettings.json文件中。典型的连接字符串为:
"ConnectionStrings": {
"MVCMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MVCMovieContext;Trusted_Connection=True;MultipleActiveResultSets=true",
}
ASP.NET Core MVC中的appsetting.json文件中, 数据库连接连接字符串中的 \ 符号没有自动转义,出现\需要双斜杠\\来转义。
可以将appsetting.json文件中连接字符串改为 Data Source, Initial Catalog双单词表示的形式,结果一样可以正常运行。如
"ConnectionStrings": {
"MVCMovieContext": "Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=MVCMovieContext;Trusted_Connection=True;MultipleActiveResultSets=true"
}
但以上2种方法都只能将数据库保存本地计算机上的c:\user\{username}目录下,如果需要换台计算机继续来开发ASP.NET Core,需要拷贝2次,且程序与数据库不在同一个目录下,拷贝显得麻烦。能不能实现像ASP.NET MVC开发一样,将数据库就保存在应用程序所在的项目中呢?
肯定数据库连接字符串需要使用到附加 AttachDbFileName,但由于ASP.NET Core不将 |DataDirectory|作为默认系统文件。因此,不能直接使用 如AttachDbFilename=|DataDirectory|\MVCMovieContext.mdf;,况且默认的项目模板没有App_Data文件夹。
我们可以首先在ASP.NET Core 项目下新建一个名为App_Data的文件夹,用来存放mdf数据库文件。
1、如果的数据库连接字符串使用DataDirectory,即连接字符串为:
"Server=(localdb)\\mssqllocaldb;Database=MVCMovieContext-ServerSyntax;AttachDbFileName=|DataDirectory|\\MVCMovieContext.mdf;Trusted_Connection=True;MultipleActiveResultSets=true",
系统会报 ArgumentException: Invalid value for key 'attachdbfilename'. 的错误。
可见ASP.NET Core不能识别|DataDirectory|文件夹。
2、采用绝对路径的方式
数据库文件存放在C:\users\{username}文件夹下。
"Server=(localdb)\\mssqllocaldb;Database=MVCMovieContext-ServerSyntax;AttachDbFileName=C:\\users\\username\\MVCMovieContext.mdf;Trusted_Connection=True;MultipleActiveResultSets=true"
能够成功访问数据库。
既然绝对路径能够访问,那么我们就可以采用绝对路径的方法来设置来设置数据库连接字符串附加数据库文件。
ASP.NET Core 应用程序(ASP.NET MVC 2.2)中附加数据库文件的解决方法如下:
第一步:建立ASP.NET Core 项目下新建一个名为App_Data的文件夹,用来存放mdf数据库文件。
第二步:在AppSetting.json配置文件中设置连接字符串:
"MVCMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MVCMovieContext;AttachDbFileName=%ContentRootPath%\\App_Data\\MVCMovieContext.mdf;Trusted_Connection=True;MultipleActiveResultSets=true"//灰色部分显式设置数据库名,可选。
第三步:更改StartUp.cs配置文件
public class Startup
{
public Startup(IConfiguration configuration,IHostingEnvironment env)// 在构造函数中添加Web主机环境。
{
Configuration = configuration;
Env = env;
}
public IHostingEnvironment Env { get; };; //添加应用程序运行的Web主机环境属性,Env为只读属性。
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
string conn = Configuration.GetConnectionString("MVCMovieContext"); //从AppSetting.json应用配置文件中读取连接字符串,值为"Server=(localdb)\\mssqllocaldb;Database=MVCMovieContext;AttachDbFileName=%ContentRootPath%\\App_Data\\MVCMovieContext.mdf;Trusted_Connection=True;MultipleActiveResultSets=true"
if (conn.Contains("%ContentRootPath%")) //判断读取的连接字符串是否包含"%ContentRootPath%"字符串
{
conn = conn.Replace("%ContentRootPath%", Env.ContentRootPath); //用程序的根目录替换掉 =%ContentRootPath%,要区分大小写。 ContentRootPath 用于包含应用程序文件。而WebRootPath 用于包含Web服务性的内容文件,app\wwwroot\.
}
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDbContext<MVCMovieContext>(options =>
options.UseSqlServer(conn));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app) //删去原来注入的env对象,改由StartUp类的构造函数注入 。原方法签名为 public void Configure(IApplicationBuilder app,,IHostingEnvironment env);
{
if (Env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
运行程序,能够正常访问和创建数据库。
在项目的Program.cs类中的main方法中可使用Context.Database.Migrate() 使用迁移来创建数据库,使用Context.Database.EnsureCreated()来创建数据库。两者的区别在于:
I.当连接字符串所指向的数据库不存在时,
EnsureCreated,创建与现在Model匹配的数据库,不能使用迁移来更新数据库。
Migrate使用以前的所有迁移来重新创建数据库,创建的数据库中多了一个__EFMigrationsHistory表。
II.当连接字符串指向的数据库存在时:
EnsuredCreated,什么也不做。不保证现有模型与数据库匹配。 所以适用于模型快速迭代的情况,也不能保留数据库里面的数据。需要每次删除数据库,再运行程序,自动创建数据库。
Migrate,可以使用诸发控制台 add-migration name 或 命令行,dotnet ef migrations update 的迁移命令来更新数据库的结构,可以保留人工通过网页输入的测试数据。选用于测试和产品阶段。