TOC
安装 ASP.NET 5 RC1
现在的最新版本是于11月18日发布的ASP.NET 5 RC1。其具体安装方法可以参阅说明文档中的Getting Started一节。
顺带一提,如果 Visual Studio 2015 出现了“’JavaScriptWebExtensionsPackage’ 未正确加载”的问题,可以尝试以下操作(参阅 Microsoft Connect 的 Workarounds 一节)
在命令行中运行
devenv /updateconfiguration devenv /clearcache
和/或更新VS2015的 Tools for Universal Windows Apps 1.1 功能。(是的,安装过程极为缓慢。)
接下来就可以按照 Your First ASP.NET 5 Web App Using Visual Studio 的教程走下去了。
使用SQLite
顺带着试用 SQLite 作为后台数据库。不过据说 SQLite 的并发支持是锁掉整个数据库……
首先,修改 project.json,在`dependencies`小节中插入对SQLite的引用
"dependencies": { //... "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final", "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final", "EntityFramework.SQLite": "7.0.0-*", "EntityFramework.Sqlite.Design": "7.0.0-*" },
安装`Sqlite.Design`之后,才能使用 dnx ef 进行体数据模型[EF]的操作。
保存文件,VS随即会开始下载相关的 NuGet包。
接下来修改实体数据模型[EF]的数据上下文(`DbContext`)的数据连接。注意到 ASP.NET 5 默认是使用依赖项注入[DI]的。所以我不建议直接重写`ApplicationDbContext.OnConfiguring`,而应该找到注册服务的位置。在这里我们定位到 `Startup.ConfigureServices`函数,并将`AddSqlServer`修改为`AddSqlite`。
public void ConfigureServices(IServiceCollection services) { // Add framework services. //services.AddEntityFramework() // .AddSqlServer() // .AddDbContext<ApplicationDbContext>(options => // options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); services.AddEntityFramework().AddSqlite().AddDbContext<ApplicationDbContext>(options => options.UseSqlite(Configuration["Data:DefaultConnection:ConnectionString"])); // 调整用户认证设置。 services.AddIdentity<ApplicationUser, IdentityRole>(options => options.Password.RequireUppercase = options.Password.RequireLowercase = options.Password.RequireDigit = options.Password.RequireNonLetterOrDigit = false) .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddMvc(); // Add application services. services.AddTransient<IEmailSender, AuthMessageSender>(); services.AddTransient<ISmsSender, AuthMessageSender>(); }
注意到默认情况下,`ApplicationDbContext`派生自支持用户认证的`IdentityDbContext`,所以我们也可以在这里修改用户认证的选项。当然了,我只是为了方便起见,所以才把密码强度要求将到最低的……不要学我 😉
我们还需要修改连接字符串。注意到代码中`Configuration`的索引器,我们定位到 appsettings.json,修改链接字符串
{ "Data": { "DefaultConnection": { //"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-RemoteFileUploader-02527226-e969-4800-89ef-e49afee1d080;Trusted_Connection=True;MultipleActiveResultSets=true" "ConnectionString": "Data Source=site.sqlite;" } }, "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Verbose", "System": "Information", "Microsoft": "Information" } } }
关于SQLite的连接字符串格式,可以参考 ConnectionString.com (居然有这样的网站)上的 SQLite connection strings。
在网站第一次访问数据库的时候,会出现错误页面。可以根据提示创建数据库。
EF数据模型
可以使用 Code First 模式来搭建数据模型。关于数据标注[Data Annotation]的介绍,可以参阅 Entity Framework Code First Data Annotations。
SQLite的数据迁移问题
根据 EF 模型的 Code First Migration 数据迁移方法,在对数据模型进行修改后,需要在命令行中定位到项目根目录,然后运行
dnx ef migrations add ThisStage dnx ef database update
其中,`ThisStage`可以换为任意名称,用来标记当前数据库阶段,方便以后对数据库的前进/回退操作。
如果提示找不到dnx,则需要执行
dnvm use 1.0.0-rc1-final -p
如果使用的是SQLite,随后使用`ef database update`执行数据库更新时就会发现问题
Applying migration '20151125022036_AddFileEntries'. System.NotSupportedException: SQLite cannot support this migration operation. 在 Microsoft.Data.Entity.Migrations.SqliteMigrationsSqlGenerator.Generate(DropForeignKeyOperation operation, IModel model, RelationalCommandListBuilder builder) 在 Microsoft.Data.Entity.Migrations.MigrationsSqlGenerator.<>c.<.cctor>b__50_10(MigrationsSqlGenerator g, MigrationOperation o, IModel m, RelationalCommandListBuilder b) 在 Microsoft.Data.Entity.Migrations.MigrationsSqlGenerator.Generate(MigrationOperation operation, IModel model, RelationalCommandListBuilder builder) 在 Microsoft.Data.Entity.Migrations.MigrationsSqlGenerator.Generate(IReadOnlyList`1 operations, IModel model) 在 Microsoft.Data.Entity.Migrations.SqliteMigrationsSqlGenerator.Generate(IReadOnlyList`1 operations, IModel model) 在 Microsoft.Data.Entity.Migrations.Internal.Migrator.GenerateUpSql(Migration migration) 在 Microsoft.Data.Entity.Migrations.Internal.Migrator.<>c__DisplayClass12_4.<GetMigrationCommands>b__10() 在 Microsoft.Data.Entity.Migrations.Internal.Migrator.Migrate(String targetMigration) 在 Microsoft.Data.Entity.Design.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType) 在 Microsoft.Data.Entity.Commands.Program.Executor.<>c__DisplayClass7_0.<UpdateDatabase>b__0() 在 Microsoft.Data.Entity.Commands.Program.Executor.Execute(Action action) SQLite cannot support this migration operation.
注意到是`DropForeignKeyOperation`,说明SQLite对外建约束的支持可能不完善。实际上,SQLite只是一个轻型数据库(例如,SQLite在实现的时候只有NULL、INTEGER[整数]、REAL[实数]、TEXT[文本]和BLOB[数据块]这几种类型)。去网上找了一下,果然……(ref = Entity Framework Code-First Migrations support for Oracle, MySQL, PostgreSQL and SQLite)
**** The ADD FOREIGN KEY constraint operation for a foreign key, consisting of a single column, is supported for the case when a new column for the foreign key is created.
同理,SQLite也不支持AlterColumn。所以,一个比较简单的办法是,直接打开 Miigrations 文件夹中的迁移文件,注释`Migration`派生类的`Up`函数中掉包含修改外键(`DropForeignKey`、`AddForeignKey`)和修改列(`AlterColumn`)相关的操作。然后再运行
dnx ef database update
当然,这样做可能意味着无法使SQLite数据库进行平滑演进,尤其是准备对包含数据的表格进行列调整或者外键调整时。不过,在一脚踏入 SQLite 的深基坑时,这一点觉悟还是必须要有的 😉