一, EntirtyFramework(EF) 简介
EntirtyFramework 框架是一个轻量级的可扩展版本的流行实体框架数据访问技术, 微软官方提供的 ORM 工具让开发人员节省数据库访问的代码时间, 将更多的时间放到业务逻辑层代码上. EF 提供变更跟踪, 唯一性约束, 惰性加载, 查询事物等. 开发人员使用 Linq 语言, 对数据库操作如同操作 Object 对象一样省事.
EF 有三种使用场景, 1. 从数据库生成 Class(DB First),2. 由实体类生成数据库表结构 (Code First),3. 通过数据库可视化设计器设计数据库, 同时生成实体类 (Model First).
EF 架构如下:
EDM (实体数据模型):EDM 包括三个模型, 概念模型, 映射和存储模型.
概念模型 ︰ 概念模型包含模型类和它们之间的关系. 独立于数据库表的设计.
存储模型 ︰ 存储模型是数据库设计模型, 包括表, 视图, 存储的过程和他们的关系和键.
映射 ︰ 映射包含有关如何将概念模型映射到存储模型的信息.
LINQ to Entities ︰ LINQ to Entities 是一种用于编写针对对象模型的查询的查询语言. 它返回在概念模型中定义的实体.
Entity SQL: Entity SQL 是另一种炉类似于 L2E 的言语, 但相给 L2E 要复杂的多, 所以开发人员不得不单独学习它.
Object Services(对象服务): 是数据库的访问入口, 负责数据具体化, 从客户端实体数据到数据库记录以及从数据库记录和实体数据的转换.
Entity Client Data Provider: 主要职责是将 L2E 或 Entity Sql 转换成数据库可以识别的 Sql 查询语句, 它使用 Ado.NET 通信向数据库发送数据可获取数据.
ADO.NET Data Provider: 使用标准的 Ado.NET 与数据库通信.
二, EntirtyFrameworkCore(EF Core)
Entity Framework Core (EF Core) 是在 2016 年首次发布的 EF6 的完全重写. 它附带于 Nuget 包中, 是 Microsoft.EntityFrameworkCore 的主要组成部分. EF Core 是一种跨平台产品, 可以在 .NET Core 或 .NET Framework 上运行. EF Core 提供了在 EF6 中不会实现的新功能 (如备选键, 批量更新以及 LINQ 查询中的混合客户端 / 数据库评估. 但由于它是一个新代码库, 所以会缺少一些 EF6 中的功能.
EFCore 与之前的 EF 基本类似, 区别在于配置的时候有一些差异; 支持 DB First 和 Model First, 广泛使用的 Code First 模式; 也不再支持 LazyLoad.
EFCore 的数据库访问技术使用之前请先安装 Microsoft.EntityFrameworkCore 包
三, EF Core 使用 DB First
数据库优先 (DB First), 编码步骤如下:
1, 新建数据库
2, 对模型实施反向工程
- Scaffold-DbContext [-Connection] <String> [-Provider] <String> [-OutputDir <String>] [-Context <String>]
- [-Schemas <String>] [-Tables <String>] [-DataAnnotations] [ -Force] [-Project <String>]
- [-StartupProject <String>] [-Environment <String>] [<CommonParameters>]
3, 在项目中配置数据库连接字符串.
四, EF Core 使用 Code First
编码优先 (Code First), 执行步骤如下:
1, 新建模型类
2, 新建 DBContext
3, 在项目中配置数据库连接字符串
4, 执行如下命令 (数据库迁移): Add-Migration [类名], Update-Database
数据表级联, 这里主要说一下级联删除
1, 外键属性可为 NULL 的级联删除时外键属性直接设置为 null 即可
2, 外键属性不可为 NULL 级联删除时会引发异常, 需要设置删除行为 DeleteBehavior ,DeleteBehavior 的类型如下表所示
数据加载是需要重点掌握的, EF 的关联实体加载有三种方式: Lazy Loading,Eager Loading,Explicit Loading, 其中 Lazy Loading 和 Explicit Loading 都是延迟加载.
(一)Lazy Loading(惰性加载) 使用的是动态代理, 默认情况下, 如果 POCO 类满足以下两个条件, EF 就使用 Lazy Loading:
POCO 类是 Public 且不为 Sealed. 导航属性标记为 Virtual.
关闭 Lazy Loading, 可以将 LazyLoadingEnabled 设为 false, 如果导航属性没有标记为 virtual,Lazy Loading 也是不起作用的.
- /// <summary>
- /// 用户信息表
- /// </summary>
- public class User
- {
- /// <summary>
- /// 用户 ID
- /// </summary>
- //[Key]
- //[DatabaseGenerated(DatabaseGeneratedOption.Identity)] // 设置自增
- public int UserId { get; set; }
- /// <summary>
- /// 用户编码
- /// </summary>
- public string UserNo { get; set; }
- /// <summary>
- /// 用户名称
- /// </summary>
- public string UserName { get; set; }
- /// <summary>
- /// 用户电话
- /// </summary>
- public string TelPhone { get; set; }
- /// <summary>
- /// 备注
- /// </summary>
- public string Remark { get; set; }
- public virtual Orginazation Org { get; set; }
- public virtual ICollection<UserAndRole> Roles { get; set; }
- }
User 实体类
- /// <summary>
- /// 角色信息表
- /// </summary>
- public class Role
- {
- /// <summary>
- /// 角色 ID
- /// </summary>
- //[Key]
- //[DatabaseGenerated(DatabaseGeneratedOption.Identity)] // 设置自增
- public int RoleID { get; set; }
- /// <summary>
- /// 角色编码
- /// </summary>
- public string RoleNO { get; set; }
- /// <summary>
- /// 角色名称
- /// </summary>
- public string RoleName { get; set; }
- /// <summary>
- /// 备注
- /// </summary>
- public string Remark { get; set; }
- public virtual ICollection<UserAndRole> Users { get; set; }
- }
Role 实体类
- /// <summary>
- /// 部门信息表
- /// </summary>
- public class Orginazation
- {
- //private readonly ILazyLoader _lazyLoader;
- //public Orginazation(ILazyLoader lazyLoader)
- //{
- // _lazyLoader = lazyLoader;
- //}
- /// <summary>
- /// 部门 ID
- /// </summary>
- [Key]
- [DatabaseGenerated(DatabaseGeneratedOption.Identity)] // 设置自增
- public int OrgId { get; set; }
- /// <summary>
- /// 部门编码
- /// </summary>
- public string OrgNO { get; set; }
- /// <summary>
- /// 部门名称
- /// </summary>
- public string OrgName { get; set; }
- /// <summary>
- /// 备注
- /// </summary>
- public string Remark { get; set; }
- public virtual ICollection<User> Users { get; set; }
- }
Orginazation 实体类
UserAndRole
在. net Core2.0 及以上版本中使用惰性加载需要引用惰性加载代理包, EF Core 一般情况下使用惰性加载, 因此为了避免报循环引用的异常需要设置 ReferenceLoopHandling 为 Ignore
Install-package Microsoft.EntityFrameworkCore.Proxies
Startup.cs 文件显示使用惰性加载
- 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;
- });
- services.AddDbContext<CodeFirstContext>(options =>
- {
- // 注入数据库
- options.UseSqlServer(Configuration.GetConnectionString("SqlServerConnStr")).ToString();
- // 打开延迟加载代理的创建.
- options.UseLazyLoadingProxies();
- });
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddJsonOptions(options =>
- {
- // 由于使用了惰性加载, 因此需要设置此参数避免报循坏引用的异常
- options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
- });
- }
Startup.cs
- public class HomeController : Controller
- {
- private readonly CodeFirstContext _dbContext;
- public IConfiguration Configuration { get; }
- string conn = string.Empty;
- public HomeController(CodeFirstContext _context)
- {
- _dbContext = _context;
- }
- public IActionResult Index()
- {
- Role role = new Role
- {
- RoleNO = "0001",
- RoleName = "管理员角色",
- Remark = "所有权限"
- };
- Orginazation org = new Orginazation
- {
- OrgNO = "00001",
- OrgName = "总公司",
- Remark = "部门根节点"
- };
- User user = new User
- {
- UserNo = "admin",
- UserName = "管理员",
- Remark = "系统管理员",
- TelPhone="22342432",
- Org = org
- };
- UserAndRole userAndRoleModel = new UserAndRole
- {
- Role = role,
- User = user,
- RoleID = role.RoleID,
- UserId = user.UserId
- };
- user.Roles.Add(userAndRoleModel);
- role.Users.Add(userAndRoleModel);
- _dbContext.Roles.Add(role);
- _dbContext.Orginazations.Add(org);
- _dbContext.Users.Add(user);
- _dbContext.UserAndRoles.Add(userAndRoleModel);
- _dbContext.SaveChanges();
- // 延迟加载
- var orgs = _dbContext.Orginazations;
- foreach (var userModel in orgs.FirstOrDefault().Users)
- {
- // 删除部门用户
- _dbContext.Users.Remove(userModel);
- }
- _dbContext.SaveChanges();
- return View();
- }
- public IActionResult About()
- {
- _dbContext.Roles.Add(new Role
- {
- RoleNO = "role1",
- RoleName = "RoleName1",
- Remark = "Remark1"
- });
- // 删除用户, 对应头像表里的数据也会被删除
- var user = _dbContext.Users.First();
- _dbContext.Users.Remove(user);
- _dbContext.SaveChanges();
- ViewData["Message"] = "Your application description page.";
- return View();
- }
- public IActionResult Contact()
- {
- ViewData["Message"] = "Your contact page.";
- return View();
- }
- public IActionResult Privacy()
- {
- return View();
- }
- [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
- public IActionResult Error()
- {
- return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
- }
- }
- HomeController
- /// <summary>
- /// Code First 编码上下文
- /// </summary>
- public class CodeFirstContext : DbContext
- {
- public CodeFirstContext(DbContextOptions<CodeFirstContext> conn)
- : base(conn)
- {
- }
- /// <summary>
- /// 映射用户信息表
- /// </summary>
- public virtual DbSet<User> Users { get; set; }
- /// <summary>
- /// 映射部门信息表
- /// </summary>
- public virtual DbSet<Orginazation> Orginazations { get; set; }
- /// <summary>
- /// 映射角色信息表
- /// </summary>
- public virtual DbSet<Role> Roles { get; set; }
- /// <summary>
- /// 用户角色信息表
- /// </summary>
- public virtual DbSet<UserAndRole> UserAndRoles { get; set; }
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- // 用户
- modelBuilder.Entity<User>(entity =>
- {
- entity.ToTable("User");
- entity.Property(e => e.UserName).IsRequired().HasMaxLength(64);
- entity.Property(e => e.UserNo).IsRequired().HasMaxLength(64);
- entity.Property(e => e.TelPhone).HasMaxLength(64);
- entity.Property(e => e.Remark).HasMaxLength(256);
- entity.HasOne(u => u.Org).WithMany(r => r.Users).OnDelete(DeleteBehavior.SetNull);
- });
- // 角色
- modelBuilder.Entity<Role>(entity =>
- {
- entity.ToTable("Role");
- entity.Property(e => e.RoleName).IsRequired().HasMaxLength(64);
- entity.Property(e => e.RoleNO).IsRequired().HasMaxLength(64);
- entity.Property(e => e.Remark).HasMaxLength(256);
- });
- // 部门信息
- modelBuilder.Entity<Orginazation>(entity =>
- {
- entity.ToTable("Orginazation");
- entity.Property(e => e.OrgNO).IsRequired().HasMaxLength(64);
- entity.Property(e => e.OrgName).IsRequired().HasMaxLength(64);
- entity.Property(e => e.Remark).HasMaxLength(256);
- // 多个用户对应一个部门
- entity.HasMany(u => u.Users).WithOne(r => r.Org).OnDelete(DeleteBehavior.SetNull);
- });
- // 用户角色信息表
- modelBuilder.Entity<UserAndRole>(entity =>
- {
- entity.ToTable("UserAndRole");
- entity.HasKey(ua => new { ua.RoleID, ua.UserId });
- });
- modelBuilder.Entity<UserAndRole>(entity =>
- {
- entity.ToTable("UserAndRole");
- entity.HasOne(u => u.Role).WithMany(r => r.Users);
- });
- modelBuilder.Entity<UserAndRole>(entity =>
- {
- entity.ToTable("UserAndRole");
- entity.HasOne(u => u.User).WithMany(r => r.Roles);
- });
- }
- }
CodeFirstContext 数据库上下文类
执行数据库迁移命令 Add-Migration init22222 结果如下:
更新数据库 Update-Database, 生成数据库表结果如下:
至此, Code First 主要步骤完成了, 通过 Code First 正确创建了表之间一对多和多对多的关系, 本实例中 User 和 Role 是多对多的关系, User 和 Orginazation 是多对一的关系,
(二)Eager Loading(预加载) 使用 Include 方法关联预先加载的实体. 在这里就不举例说明了.
(三)Explicit Loading(直接加载) 使用 Entry 方法, 对于集合使用 Collection, 单个实体则使用 Reference. 在这里就不举例说明了.
以上是我对 Entity Framework Core 的总结和使用, 欢迎纠错!!!
来源: https://www.cnblogs.com/yiliukejich0614-1234/p/10188711.html