Walden1024

导航

[翻译][MVC 5 + EF 6] 1:创建数据模型

 

原文:Getting Started with Entity Framework 6 Code First using MVC 5

 

1.新建MVC项目

New_project_dialog_box

New_project_dialog_box

New_project_dialog_box

2.修改Views\Shared\_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Contoso University</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="navbar-inner">
            <div class="container">
                <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Contoso University", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
                <div class="nav-collapse collapse">
                    <ul class="nav">
                        <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>
            </div>
        </div>
    </div>

    <div class="container">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - Contoso University</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

3.修改Views\Home\Index.cshtml

@{
    ViewBag.Title = "Home Page";
}

<div class="jumbotron">
    <h1>Contoso University</h1>
</div>
<div class="row">
    <div class="col-md-4">
        <h2>Welcome to Contoso University</h2>
        <p>Contoso University is a sample application that
        demonstrates how to use Entity Framework 6 in an 
        ASP.NET MVC 5 web application.</p>
    </div>
    <div class="col-md-4">
        <h2>Build it from scratch</h2>
        <p>You can build the application by following the steps in the tutorial series on the ASP.NET site.</p>
        <p><a class="btn btn-default" href="http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/">See the tutorial &raquo;</a></p>
    </div>
    <div class="col-md-4">
        <h2>Download it</h2>
        <p>You can download the completed project from the Microsoft Code Gallery.</p>
        <p><a class="btn btn-default" href="http://code.msdn.microsoft.com/ASPNET-MVC-Application-b01a9fe8">Download &raquo;</a></p>
    </div>
</div>

4.安装EFTools --> NuGet Package Manager --> Package Manager Console

Install-Package EntityFramework

5.创建模型

Class_diagram

namespace ContosoUniversity.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; }
    }
}

  ID将会对应数据库中该类对应的数据表的主键列。默认情况下,EF会将名为ID或classnameID的属性当作主键。

  Enrollments是导航属性。导航属性表示其他实体与本实体关联。

  将导航属性定义为virtual,这样可以使用EF的一些功能,例如延迟加载。

  如果导航属性为一对多或多对多关系,它的类型需要为集合类型,例如ICollection。

namespace ContosoUniversity.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; }
    }
}

  与Student中使用ID不同的是Enrollment中使用classnameID模式。一般情况下,我们在模型设计阶段只是用两种模式中的一种。但使用ID模式在数据模型中实现继承会更加容易。

  Grade是枚举类型,问号表示其是可空类型。

  StudentID是外键,对应导航属性Student。一个Enrollment实体紧对应一个Student实体。

  如果一个属性名为导航属性的<导航属性名>+<主键属性名>,EF则会把它作为外键,例如StudentID为<Student>+<ID>。如果一个属性名为导航属性的<主键属性名>,EF也会把它作为外键,例如CourseID为Course的主键。

namespace ContosoUniversity.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.添加数据库上下文

  项目根目录添加名为DAL的文件夹,并在该文件夹下添加:

namespace ContosoUniversity.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>();
        }
    }
}

  为每个实体集添加DbSet属性,则该实体就对应一个数据表。

  上面的代码中可以去掉DbSet<Enrollment>和DbSet<Course>声明,EF会隐含的包含它们。因为Student引用了Enrollment,而Enrollment又引用了Course。

  "SchoolContext"表示定义在Web.config中的数据库连接字符串。如果不使用Web.config的字符串,我们也可以传递一个完整的连接字符串。如果我们不指定连接字符串,EF会假定连接字符串的名字为上下文类的类名,如在本例中为"SchoolContext"。[更多请参考:Entity Framework - Connections and Models]

  modelBuilder.Conventions.Remove代码的功能是在创建数据表时将表命名为单数形式,如Student、Enrollment和Course。如果不加此代码,数据表将会被命名为Students、Enrollments和Courses。这个可以根据个人命名习惯决定是否添加。

7.添加初始化数据

  EF会在程序运行时为我们自动创建(或删除重建)一个数据库。我们可以指定这个动作是在每次程序运行时执行还是在模型发生变化时执行。

  EF默认的行为是在数据库不存在时新建一个数据库(如果一个数据库已经存在,则在模型发生改变的时候抛出异常)。在本节教程,我们指定数据库在模型发生变化时删除后重建。删除数据库会造成数据的丢失,这在开发环境下一般是可以接受的,但是在正式产品中,我们不希望在数据库模型发生改变的时候丢失数据。稍后我们将会看到如何使用代码优先迁移(Code First Migrations)来取代在数据库模型发生变化时删除后重建

  7.1.添加初始化数据类:

 

namespace ContosoUniversity.DAL
{
    public class SchoolInitializer : 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=1050,Title="Chemistry",Credits=3,},
            new Course{CourseID=4022,Title="Microeconomics",Credits=3,},
            new Course{CourseID=4041,Title="Macroeconomics",Credits=3,},
            new Course{CourseID=1045,Title="Calculus",Credits=4,},
            new Course{CourseID=3141,Title="Trigonometry",Credits=4,},
            new Course{CourseID=2021,Title="Composition",Credits=3,},
            new Course{CourseID=2042,Title="Literature",Credits=4,}
            };
            courses.ForEach(s => context.Courses.Add(s));
            context.SaveChanges();
            var enrollments = new List<Enrollment>
            {
            new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
            new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
            new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
            new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
            new Enrollment{StudentID=3,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=1050,},
            new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
            new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
            new Enrollment{StudentID=6,CourseID=1045},
            new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };
            enrollments.ForEach(s => context.Enrollments.Add(s));
            context.SaveChanges();
        }
    }
}

 

  在seed方法中我们可以在添加完成所有的数据后再SaveChanges方法,但是上面的方式可以在插入数据异常时定位问题发生点。

  7.2.添加初始化数据类的引用:

    7.2.1.方法一(添加配置):

<entityFramework>
  <contexts>
    <context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
      <databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" />
    </context>
  </contexts>
    <!-- 其余省略 -->
</entityFramework>

  这是为了告诉EF在新建数据库时调用插入初始化数据类。

  context type指定上下文类和程序集,databaseInitializer type指定初始化数据类和程序集。如果想要取消插入初始化数据,可以在context添加属性:

<context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity" disableDatabaseInitialization="true">

    7.2.2.方法二(Global.asax.csApplication_Start方法中添加):

Database.SetInitializer(new SchoolInitializer());

  更多信息请查看:Understanding Database Initializers in Entity Framework Code First

8.使用SQL Server Express LocalDB数据库

  添加配置:

  <connectionStrings>
    <add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;AttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf;
         Initial Catalog=ContosoUniversity1;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
  </connectionStrings>

  此配置将会在项目的App_Data文件夹创建数据库文件。

  如果我们没有添加连接字符串,EF会根据上下文类使用使用一个默认连接。

9.添加Student控制器和视图

  首先编译项目。

Add Scaffold

Add_Controller_dialog_box_for_Student_controller

10.运行程序

Menu button

Student Index page

11.查看数据库

Student table

 

  其他的EF资源:ASP.NET Data Access - Recommended Resources

 

posted on 2015-06-12 11:59  Walden1024  阅读(363)  评论(0编辑  收藏  举报