【EF6学习笔记】(一)Code First 方式生成数据库及初始化数据库实际操作
本篇参考原文地址:
Creating an Entity Framework Data Model
说明:学习笔记参考原文中的流程,为了增加实际操作性,并能够深入理解,部分地方根据实际情况做了一些调整;并且根据自己的理解做了一些扩展。
本人的学习环境: VS2017 + EF 6.1.3 + .NET 4.6.1
Step1 : 新建Web Application (我起名为EFTest)

选择空白模板,但勾选 MVC 的Folder reference.

Step2: 通过Package Manager Console来安装EF6


Step3: 新建一个LocalDB的空的测试数据库



Step4: 新建一个 主页面 作为基础入口(在Controller目录下新建一个空的Controller, 起名字就为Home 即可)



然后在Home Controller的Index Action上右键点击来增加Index View: (就选空的View就可以,测试嘛,能简单就简单)


并将Home/Index View中修改为以下代码:

@{
ViewBag.Title = "Hello EF6";
}
<h2>Hello EF6</h2>
<div>
<ul>
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Students", "Index", "Student")</li>
<li>@Html.ActionLink("Courses", "Index", "Course")</li>
<li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>
<li>@Html.ActionLink("Departments", "Index", "Department")</li>
</ul>
</div>

Step5: 在Web.config中增加 数据库字符串;
<connectionStrings>
<add name="SchoolContext" connectionString="Data Source=(localdb)\ProjectsV13;Initial Catalog=EFTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;" providerName="System.Data.SqlClient"/>
</connectionStrings>
注:可以点击 SQLServer Object Explorer中的数据库,然后在 属性页中,可以拷贝出该数据库的连接字符串;

Step6: 正式开始EF学习测试相关的操作:
6.1 在Models目录下新建 Student类

using System;
using System.Collections.Generic; namespace EFTest.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}

6.2 在Models目录下新建Course类

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}

6.3 在Models目录下新建Enrollment类

namespace EFTest.Models
{
public enum Grade
{
A, B, C, D, F
} public class Enrollment
{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public Grade? Grade { get; set; } public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
}

通过类定义可以看到: 一个学生可以选修多个课程(有多个课程记录),一个课程可以多个学生选修(有多个学生记录);
一个课程记录对应一个学生一门课程;
那么对于课程记录,学生ID和课程ID就是外键;必须先存在某个学生,才可以有这个学生的课程记录,也必须先存在某个课程,才可以由这个课程的课程记录;
6.4 新建一个DAL文件夹(数据访问层),新建 SchoolContext 类和SchoolInitializer类;
说明:SchoolContext类从DbContext继承,并在构造函数中定义 数据库字符串名:base("SchoolContext") ,然后通过DbSet<T>定义数据库模型;
最后还重载了OnModelCreating方法,用来改变一些约束;(如果例子中的表名不用变复数,以及其它约束,比如改表名、列名等等);

using EFTest.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions; namespace EFTest.DAL
{
public class SchoolContext : DbContext
{
public SchoolContext() : base("SchoolContext")
{
} public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}

说明:SchoolInitializer类用来定义数据库在初始化的时候需要做的一些事情;比如通过重载Seed方法预先放入一些数据等;

using System;
using System.Collections.Generic;
using EFTest.Models; namespace EFTest.DAL
{
public class SchoolInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<SchoolContext>
{
protected override void Seed(SchoolContext context)
{
var students = new List<Student>
{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
}; students.ForEach(s => context.Students.Add(s));
context.SaveChanges();
var courses = new List<Course>
{
new Course{CourseID=,Title="Chemistry",Credits=,},
new Course{CourseID=,Title="Microeconomics",Credits=,},
new Course{CourseID=,Title="Macroeconomics",Credits=,},
new Course{CourseID=,Title="Calculus",Credits=,},
new Course{CourseID=,Title="Trigonometry",Credits=,},
new Course{CourseID=,Title="Composition",Credits=,},
new Course{CourseID=,Title="Literature",Credits=,}
};
courses.ForEach(s => context.Courses.Add(s));
context.SaveChanges();
var enrollments = new List<Enrollment>
{
new Enrollment{StudentID=,CourseID=,Grade=Grade.A},
new Enrollment{StudentID=,CourseID=,Grade=Grade.C},
new Enrollment{StudentID=,CourseID=,Grade=Grade.B},
new Enrollment{StudentID=,CourseID=,Grade=Grade.B},
new Enrollment{StudentID=,CourseID=,Grade=Grade.F},
new Enrollment{StudentID=,CourseID=,Grade=Grade.F},
new Enrollment{StudentID=,CourseID=},
new Enrollment{StudentID=,CourseID=,},
new Enrollment{StudentID=,CourseID=,Grade=Grade.F},
new Enrollment{StudentID=,CourseID=,Grade=Grade.C},
new Enrollment{StudentID=,CourseID=},
new Enrollment{StudentID=,CourseID=,Grade=Grade.A},
};
enrollments.ForEach(s => context.Enrollments.Add(s));
context.SaveChanges();
}
}
}

Step7: 定义数据库初始化(本章不涉及数据库迁移等,迁移以后再说)
第6步定义了上下文类以及初始化类,那么怎么让应用在执行时候进行数据库初始化动作?
有两种方式:(只能选一种)
1、在Web.config 中定义:
在<entityFramework>节点中,增加<contexts>节点,分别定义<context>的type ,以及初始化<databaseInitializer>的type: (具体为啥这样定义,只能以后看原理。。。)

<entityFramework>
<contexts>
<context type="EFTest.DAL.SchoolContext, EFTest">
<databaseInitializer type="EFTest.DAL.SchoolInitializer, EFTest" />
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>

2、在Global.asax中执行初始化;在Application_Start()方法中,最后加上以下数据库初始化代码:
Database.SetInitializer<SchoolContext>(new SchoolInitializer());
注:第1种方法,在Home/Index页面打开的时候是不会初始化数据库的,因为还没操作数据库读写。。。下面加访问页面来进行数据库读取;
Step8: 增加一个 Student Controller , 直接选择空白的就可以,通过敲入代码来更多理解:

先为Student控制器加一个SchoolContext db , 然后把Student/Index的return View()改为如下:

using EFTest.DAL;
using System.Linq;
using System.Web.Mvc; namespace EFTest.Controllers
{
public class StudentController : Controller
{
private SchoolContext db = new SchoolContext(); // GET: Student
public ActionResult Index()
{
return View(db.Students.ToList());
}
}
}


为Index Action加View, 选择List模板 , Model 选Student , 然后再选择好上下文类:

注:如果出现以下错误,则表示先要编译一下,再建View

Step9: 执行起来看看 Student/Index 页面:

也可以查看一下数据库,已经新建成功:

学习整理总结:
1、根据ASP.NET MVC的概念,约定大于配置,EF6同样存在;
数据类定义中,如果名为ID的,则自动为主键,如果为类名+ID的,也会自动为主键; 其他属性名自动为列表;如果为int型,则会默认为自增长主键;
比较神奇的是外键的自动创建,这个约束描述起来好累,实际看看代码和实际数据库的外键就能明白;
(通过加 virtual 描述来实现延时数据加载,即程序用到这个属性定义的数据时,才会去查数据库)
2、 既然有约定就可以改变约定;
可以通过对属性增加 Annotations注释 来改变约定,例如:修改主键不要为自增加主键,改变列表,增加其他列为主键,设定字段长度等等;
如:[DatabaseGenerated(DatabaseGeneratedOption.None)]
【EF6学习笔记】(一)Code First 方式生成数据库及初始化数据库实际操作的更多相关文章
- EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作
EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习 ...
- 【EF6学习笔记】目录
[EF6学习笔记](一)Code First 方式生成数据库及初始化数据库实际操作 [EF6学习笔记](二)操练 CRUD 增删改查 [EF6学习笔记](三)排序.过滤查询及分页 [EF6学习笔记]( ...
- ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)
个人从传统的CS应用开发(WPF)开始转向BS架构应用开发: 先是采用了最容易上手也是最容易搞不清楚状况的WebForm方式入手:到后面就直接抛弃了服务器控件的开发方式,转而采用 普通页面+Ajax+ ...
- EF6 学习笔记(二):操练 CRUD 增删改查
EF6学习笔记总目录 ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 接上篇: EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作 本篇原文链接: I ...
- EF6学习笔记(六) 创建复杂的数据模型
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇原文地址:Creating a More Complex Data Model 本篇讲的比较碎,很多内容本人 ...
- EF6 学习笔记(五):数据库迁移及部署
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 原文地址:Code First Migrations and Deployment 原文主要讲两部分:开发环境下 ...
- EF6学习笔记(四) 弹性连接及命令拦截调试
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本章原文地址:Connection Resiliency and Command Interception 原文 ...
- EF6 学习笔记(三):排序、过滤查询及分页
EF6 学习笔记索引目录页: ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇:EF6 学习笔记(二):操练 CRUD 增删改查 本篇原文地址:Sorting, Filterin ...
- 【Unity Shaders】学习笔记——SurfaceShader(八)生成立方图
[Unity Shaders]学习笔记——SurfaceShader(八)生成立方图 转载请注明出处:http://www.cnblogs.com/-867259206/p/5630261.html ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第四章:Direct 3D初始化 学习目标 对Direct 3D编程在 ...
随机推荐
- 别人的Linux私房菜(13)学习Shell脚本
CentOS6.x以前版本的系统服务启动接口在/etc/init.d/目录下,存放了脚本. Shell脚本因调用外部命令和bash 的一些默认工具,速度较慢,不适合处理大量运算. 执行方式有:直接命令 ...
- python作业练习
#1.猜字游戏 用if分支完成猜数字游戏 -- 先通过键盘输入一个数字算作出题 -- 在键盘输入答案 -- 正确:猜对 | 误差3以内:接近了 | 误差外小值:太小 | 误差外大值:太大 queste ...
- 剑指offer PART 2
剑指offer PART 2 书点击自取 提取码: njku 标签(空格分隔): 笔记 C++知识点: 1.面向对象的特性 2.构造函数 3.析构函数 4.动态绑定 5.常用的设计模式 6.UML图 ...
- 偏差(Bias)和方差(Variance)——机器学习中的模型选择zz
模型性能的度量 在监督学习中,已知样本 ,要求拟合出一个模型(函数),其预测值与样本实际值的误差最小. 考虑到样本数据其实是采样,并不是真实值本身,假设真实模型(函数)是,则采样值,其中代表噪音,其均 ...
- appium解决每次运行都需要安装Unlock以及AppiumSetting的问题
这是我用appium遇到的第三个坑?之前因为环境的问题,chromedriver驱动总是安装不对,后来发现是因为路径的原因.解决之后,现在出现新的问题,那就是“appium每次运行都要去重新安装Unl ...
- Linux学习---位运算符
<<.>> ① << 左移 乘以2^n m << n m*(2^n) eg:4: 0 0 1 0 0 8: 0 1 0 0 0 [数据.数字]移位 左 ...
- mqtt mosquitto 源码安装
下载地址 ububtu : wget https://codeload.github.com/eclipse/mosquitto/zip/master 安装依赖 sudo apt-get insta ...
- mycat跟踪分析
mycat版本1.6 192.168.5.66 从 192.168.5.67主 一个user表 验证主从 log4j2修改日志level为debug schema.xml配置 启动服务,打开日志tai ...
- position 小结
position: static fixed relative absolute sticky 1.static static定位是HTML元素的默认值,即没有定位,元素出现在正常的流中.因此,这种定 ...
- Chapter 7 Resources in Plug-In(1)
Activity and resource are like twin brothers. And so if the activity need to be solve in Plug-In com ...