22-EF Core和SqlServer的使用-生成数据库
一个ORM 对象关系模型,支持多数据库:SQLserver、SQLite、Npgsql、MySql 等等。
获取EF Code-sqlserver:
Install-Package Microsoft.EntityFrameworkCore.SqlServerCode language: CSS (css)
PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer
GET https://api.nuget.org/v3/registration3-gz-semver2/microsoft.entityframeworkcore.sqlserver/index.json
OK https://api.nuget.org/v3/registration3-gz-semver2/microsoft.entityframeworkcore.sqlserver/index.json 352 毫秒
正在还原 E:\FoxDevelop.com视频\137-ASP.NET CORE 视频教程\EFCoreDemo\EFCoreDemo\EFCoreDemo.csproj 的包...
正在安装 NuGet 程序包 Microsoft.EntityFrameworkCore.SqlServer 2.0.2。
正在提交还原...
将锁定文件写入磁盘。路径: E:\FoxDevelop.com视频\137-ASP.NET CORE 视频教程\EFCoreDemo\EFCoreDemo\obj\project.assets.json
E:\FoxDevelop.com视频\137-ASP.NET CORE 视频教程\EFCoreDemo\EFCoreDemo\EFCoreDemo.csproj 的还原在 491.07 ms 内完成。
执行 nuget 操作花费时间 2.2 sec
已用时间: 00:00:05.0025412
PM>Code language: JavaScript (javascript)
EF Core 通过模型进行数据访问。模型由实体类和会话组成(上下文),会话是和数据库进行通讯的。
两种方式使用EF Core:
- Database First:数据库生成模型
- Code First:模型生成数据库
下面编写上下文和模型。一个博客的上下文,添加一个BloggingContext的类 继承之DbContext:
public class BloggingDbContext : DbContext
{
//下面两个dbset 会被映射成数据库里面的表 数据库下面配置
public DbSet<Blog> Blogs { set; get; }
public DbSet<Post> Posts { set; get; }
//重写OnConfiguring事件 设置数据库连接
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"server=.;database=efcoredb;Trusted_Connection=True;");
}
}Code language: HTML, XML (xml)
生成数据库,使用命令通过代码生成数据库。打开nuget管理器:
先输入:Add-Migration MyFirstMigration(名字)
再输入:Update-Database
PM> Add-Migration MyFirstMigration
Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:\Users\YY\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
To undo this action, use Remove-Migration.
PM> Update-Database
Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:\Users\YY\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
Applying migration '20180401033242_MyFirstMigration'.
Done.
PM>Code language: JavaScript (javascript)
经过上面两个命令 然后我们就打开数据库sqlserver 就可以看到生成的数据库。
参考:https://blog.csdn.net/aojiancc2/article/details/76615653
常见异常:
System.ArgumentException
HResult=0x80070057
Message=AddDbContext was called with configuration, but the context type 'BloggingDbContext' only declares a parameterless constructor. This means that the configuration passed to AddDbContext will never be used. If configuration is passed to AddDbContext, then 'BloggingDbContext' should declare a constructor that accepts a DbContextOptions<BloggingDbContext> and must pass it to the base constructor for DbContext.
Source=Microsoft.EntityFrameworkCoreCode language: JavaScript (javascript)
Blog类-一对多的关系:
public class Blog
{
public int BlogId { set; get; }
public int Rating { set; get; }
public string Url { set; get; }
public List<Post> Posts { set; get; }
}Code language: JavaScript (javascript)
博文表Post 一片文章一个Blog:
public class Post
{
public int PostId { set; get; }
public string Title { set; get; }
public string Content { set; get; }
public int BlogId { set; get; }
public Blog Blog { set; get; }
}Code language: JavaScript (javascript)
23-EF CORE查询和新增-使用LINQ查询数据
下面我们再Home控制器里面 进行数据查询:
public IActionResult Index()
{
//调用ef core 上下文进行数据查询
using (var db = new BloggingDbContext())
{
var blogs = db.Blogs
.Where(b => b.Rating > 3)
.OrderBy(b => b.Url)
.ToList();
ViewBag.BlogList = blogs;
}
return View();
}Code language: JavaScript (javascript)
当然我们上面 数据库刚生成 所以还没有数据 下面我们来使用ef core 新增一条数据库:
public IActionResult Index()
{
using (var db = new BloggingDbContext())
{
//使用ef core 插入数据
var blog = new Blog { Rating = 20, Url = "www.FoxDevelop.com" };
db.Blogs.Add(blog);
db.SaveChanges();
//使用ef core 上下文进行数据查询
var blogs = db.Blogs
.Where(b => b.Rating > 3)
.OrderBy(b => b.Url)
.ToList();
ViewBag.BlogList = blogs;
}
return View();
}Code language: JavaScript (javascript)
视图中呈现数据列表 找到Home目录下面的Index视图:
@{
ViewData["Title"] = "Home Page";
var blogList = ViewBag.BlogList as List<Blog>;
}
<div class="col-md-3">
<h2>博客列表</h2>
<ul>
@for (int i = 0; i < blogList.Count; i++)
{
<li><a href="@blogList[i].Url">@blogList[i].Url</a></li>
}
</ul>
</div>Code language: JavaScript (javascript)
24-CodeFirst 方式使用Sqlite
新建一个EfcoreSqlite的项目。Nuget安装sqlite支持:
Install-Package Microsoft.EntityFrameworkCore.SqliteCode language: CSS (css)
PM> Install-Package Microsoft.EntityFrameworkCore.Sqlite
GET https://api.nuget.org/v3/registration3-gz-semver2/microsoft.entityframeworkcore.sqlite/index.json
OK https://api.nuget.org/v3/registration3-gz-semver2/microsoft.entityframeworkcore.sqlite/index.json 308 毫秒
正在还原 E:\FoxDevelop.com视频\137-ASP.NET CORE 视频教程\EfcoreSqlite\EfcoreSqlite\EfcoreSqlite.csproj 的包...
正在安装 NuGet 程序包 Microsoft.EntityFrameworkCore.Sqlite 2.0.2。
正在提交还原...
E:\FoxDevelop.com视频\137-ASP.NET CORE 视频教程\EfcoreSqlite\EfcoreSqlite\EfcoreSqlite.csproj 的还原在 566.12 ms 内完成。
执行 nuget 操作花费时间 1.84 sec
已用时间: 00:00:05.8583027
PM>Code language: JavaScript (javascript)
新增实体类:
namespace EfcoreSqlite.Models
{
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
}Code language: JavaScript (javascript)
创建上下文:
namespace EfcoreSqlite.Models
{
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
public DbSet<User> Users { set; get; }
}
}Code language: HTML, XML (xml)
创建数据库,Startup下面先引用 using Microsoft.EntityFrameworkCore; 然后:
public void ConfigureServices(IServiceCollection services)
{
var connection = "Filename=./ecsqlite.db";
services.AddDbContext<DataContext>(options => options.UseSqlite(connection));
services.AddMvc();
}Code language: JavaScript (javascript)
方便操作数据库ef 安装EntityFrameworkCore Tool,执行nuget命令:
Install-package microsoft.entityframeworkcore.tools -preCode language: CSS (css)
PM> Install-package microsoft.entityframeworkcore.tools -pre
GET https://api.nuget.org/v3/registration3-gz-semver2/microsoft.entityframeworkcore.tools/index.json
OK https://api.nuget.org/v3/registration3-gz-semver2/microsoft.entityframeworkcore.tools/index.json 394 毫秒
正在还原 ...\EfcoreSqlite.csproj 的包...
GET https://api.nuget.org/v3-flatcontainer/microsoft.entityframeworkcore.tools/index.json
OK https://api.nuget.org/v3-flatcontainer/microsoft.extensions.configuration.abstractions/2.1.0-preview1-final/microsoft.extensions.configuration.abstractions.2.1.0-preview1-final.nupkg 220 毫秒
正在安装 Microsoft.Extensions.Configuration.Abstractions 2.1.0-preview1-final。
...
已将“Microsoft.EntityFrameworkCore.Design 2.1.0-preview1-final”成功安装到 EfcoreSqlite
执行 nuget 操作花费时间 2.69 sec
已用时间: 00:00:16.3804816
PM>Code language: PHP (php)
数据库迁移和执行:
E:\...\EfcoreSqlite> dotnet ef migrations add mysecondmigration
未找到与命令“dotnet-ef”匹配的可执行文件
.net core 2.0 dbfirst 报 dotnet ef 未找到与命令“dotnet-ef”匹配的可执行文件的解决办法:右击项目弹出菜单点击编辑 ***.csproj,增加如下配置:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>Code language: HTML, XML (xml)
E:\...\EfcoreSqlite> dotnet ef migrations add MySecMigration
Build failed.
E:\...\EfcoreSqlite> dotnet ef
_/\__
---==/ \\
___ ___ |. \|\
| __|| __| | ) \\\
| _| | _| \_/ | //|\\
|___||_| / \\\/\\
Entity Framework Core .NET Command Line Tools 2.0.0-rtm-26452
Usage: dotnet ef [options] [command]
...Code language: PHP (php)
dotnet ef migrations add InitialCreate
# 提交到数据库
dotnet ef database updateCode language: PHP (php)
E:\...\EfcoreSqlite> dotnet ef migrations add InitialCreate
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
User profile is available. Using 'C:\Users\YY\AppData\Local\ASP.NET\DataProtection-Keys' ...
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 2.0.2-rtm-10011 initialized 'DataContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: None
Done. To undo this action, use 'ef migrations remove'Code language: JavaScript (javascript)
需要再上下文中引入命名空间 Microsoft.EntityFrameworkCore.Sqlite,需要安装 Install-package Microsoft.EntityFrameworkCore.Sqlite。
生成数据库文件:
public void ConfigureServices(IServiceCollection services)
{
//var connection = "Filename=./ecsqlite.db";
//services.AddDbContext<DataContext>(options=> options.UseSqlite(connection));
services.AddDbContext<DataContext>();
services.AddMvc();
}Code language: JavaScript (javascript)
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
public DbSet<User> Users { set; get; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=blogging.db");
}
}Code language: HTML, XML (xml)
注意事项:开发调试时默认生成的数据库文件所在目录为 bin/Debug/netcoreapp1.1/blogging.db。发布后,应该把数据库文件拷贝到发布程序的根目录里,不然报错,找不到数据库文件。
24-解决sqlite数据库没法创建的问题
Nuget中安装:
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.Sqlite
- Microsoft.EntityFrameworkCore.Tools.DotNet
在DataContext中指定数据连接串:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=data.db");
}Code language: JavaScript (javascript)
原来是在Startup中指定的,修改ConfigureServices:
// 原来
public void ConfigureServices(IServiceCollection services)
{
var connection = "Filename=./ecsqlite.db";
services.AddDbContext<DataContext>(options => options.UseSqlite(connection));
services.AddMvc();
}
// 修改后
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>();
services.AddMvc();
}Code language: JavaScript (javascript)
安装Tools.DotNet时可能遇到的包降级错误:
PM> Install-Package Microsoft.EntityFrameworkCore.Tools.DotNet
NU1605: 检测到包降级: Microsoft.NETCore.App 从 2.0.6 降级到 2.0.0...
Install-Package : 程序包还原失败。正在回滚“EfcoreSqlite”的程序包更改。Code language: CSS (css)
解决办法:去掉csproj里面之前根据网上加的虚假安装配置。
新建User控制器:
namespace EfcoreSqlite.Controllers
{
public class UserController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Register()
{
return View();
}
}
}
右击action添加视图,最后生成的视图:
Index视图:
@model IEnumerable<EfcoreSqlite.Models.User>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p><a asp-action="Create">Create New</a></p>
<table class="table">
<thead>
<tr>
<th>@Html.DisplayNameFor(model => model.UserName)</th>
<th>@Html.DisplayNameFor(model => model.Password)</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>@Html.DisplayFor(modelItem => item.UserName)</td>
<td>@Html.DisplayFor(modelItem => item.Password)</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>Code language: HTML, XML (xml)
Register视图:
@model EfcoreSqlite.Models.User
@{
ViewData["Title"] = "Register";
}
<h2>Register</h2>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Register">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div><a asp-action="Index">Back to List</a></div>Code language: HTML, XML (xml)
完成action的Post操作:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Register(User info)
{
if (ModelState.IsValid)
{
using (var db = new DataContext())
{
db.Users.Add(info);
db.SaveChanges();
}
}
return View();
}Code language: PHP (php)
列表页呈现:
public IActionResult Index()
{
using (var db = new DataContext())
{
var blogs = db.Users.ToList();
return View(blogs);
}
}Code language: PHP (php)