ORM
对象关系映射 Object / Relational Mapping
定义:用来把对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中去。
ORM技术是在对象和关系之间提供了一条桥梁,前台的对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化。
Entity Framework
Entity Framework 的三种工作方式:
-
Model First
创建ADO.NET实体对象以及它们之间的关系,然后再指定到数据库的映射。 -
Database First
在分析需求后开始创建数据库中的表,一旦表确定后变动不会太大或者几乎不再去更改表的结构,后面的模型编写及业务逻辑的编写都在这个基础上进行。 -
Code First
先用C#.NET的类定义好领域模型,然后用这些类映射到现有的数据库或者产生新的数据库结构。
Code First
接下来将介绍
- 如何使用类定义模型来创建数据库并存储和检索数据
- 如何根据模型改变使用Code First 迁移(Migrations)改变数据库架构
- 如何使用Data Annotations和Fluent API来配置模型
本文参考了Mricosoft Docs提供的Code First to a new database进行演示:
1.创建模型
a.新建控制台应用程序BlogEF
b.创建类Blog和类Post
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
2.创建上下文
a.NuGet中安装EntityFramework 包
b.创建类BloggingContext
using System.Data.Entity;
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
3.读取和写入数据
class Program
{
static void Main(string[] args)
{
using (var db = new BloggingContext())
{
for (int i = 0; i < 10; i++)
{
var blog = new Blog() { Name = "Lunafougere" + i.ToString()};
db.Blogs.Add(blog);
db.SaveChanges();
}
var query = from b in db.Blogs
orderby b.Name
select b;
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
}
Console.ReadKey();
}
}
运行程序后,vs中视图–>SQLServer对象资源管理器
DbContext 按照约定创建数据库,在SQLServer对象资源管理器中可以看到新增了数据库BlogEF.BloggingContext,新增了表Blogs和表Posts。
4.处理模型修改
当我们需要修改对象模型时,还需要更新对应的数据库,这一操作称为Code first 迁移(migration)。
a.在类Blog中新增Url属性
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; } //新增Url属性
public virtual List<Post> Posts { get; set; }
}
vs中工具–>NuGet包管理器–>程序包管理器控制台
此时vs面板中会出现“程序包管理器控制台”:
b.在程序包管理器控制台中使用cd命令切换目录到项目目录中,执行命令: Enable-Migrations
此时项目中会新增文件夹 Migrations及文件 <时间戳>_InitialCreate.cs、Configuration.cs。
- <时间戳>_InitialCreate.cs
这是第一次迁移,呈现了从空数据库到新增表Blogs和表Posts的更改。
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Blogs",
c => new
{
BlogId = c.Int(nullable: false, identity: true),
Name = c.String(),
})
.PrimaryKey(t => t.BlogId);
CreateTable(
"dbo.Posts",
c => new
{
PostId = c.Int(nullable: false, identity: true),
Title = c.String(),
Content = c.String(),
BlogId = c.Int(nullable: false),
})
.PrimaryKey(t => t.PostId)
.ForeignKey("dbo.Blogs", t => t.BlogId, cascadeDelete: true)
.Index(t => t.BlogId);
}
public override void Down()
{
DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs");
DropIndex("dbo.Posts", new[] { "BlogId" });
DropTable("dbo.Posts");
DropTable("dbo.Blogs");
}
}
c.执行命令:Add-migration AddUrl
同时项目文件夹 Migrations中新增- <时间戳>_AddUrl.cs
d.执行命令:Update-database
更新迁移后,表Blogs新增字段Url:
5.Data Annotations(批注)
a.新增类User
public class User
{
public string Username { get; set; }
public string DisplayName { get; set; }
}
b.添加User的Dbset到派生上下文BloggingContext
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
}
此时执行命令Add-migration AddUser 会报错:
报错原因:在类User中未按照约定对主键定义(主键约定:属性命名为XXId),因此要添加批注(Annotations)确定主键。
c.现在属性Username上添加[Key]:
d.执行命令:Add-migration AddUser
6.Fluent API
是处理Data Annotations不能处理的更高级的模型配置
eg:处理对象模型属性名称和数据库表字段名称不一致的场景
a.重写BloggingContext的OnModelCreating方法,对属性进行重命名
将User中DisplayName改为 display_name
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
//重写OnModelCreating方法对属性进行重命名
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Property(u => u.DisplayName)
.HasColumnName("display_name");
}
}
b.执行命令:Add-migration ModifyUserDisplayName
c.执行命令:Update-database
查看数据库表User中字段已重命名为display_name:
总结
本文简单介绍了EF的 Code First 工作方式,使用vs创建类模型及上下文通过EF code first创建数据库并存储和检索数据,当类模型改变时使用Code First 迁移(Migrations)改变数据库架构,其中使用Data Annotations指定主键,使用Fluent API对属性进行重命名。
(我的第一篇博客,有点小激动,初学者,望各位前辈多多指教!)