• EF直接的一對多多對多多對一的關係----也即是鏈錶查詢


    基于EF4.1 code first 简单的CRUD  园子中已经有很多了 ~~ 真不想再写这个了 可是为了做一个完整的小demo 从开始 到后面的一些简单重构 还是决定认真把这个写出来

    争取写些别人没写到的东西~~ 好了 开始~~

    这次要做的是个学校管理的demo(通俗些)

     先建一个MVC3的应用程序  因为我们是code first 所以 开始创建实体类

    一.创建Model

    学生和学生成绩登记表是一对多的关系  一个学生可以有多次登记 (因为有多个课程)  一个课程也可以有多个登记   可以看出 其实就是 学生和课程 存在一个多对多的关系

    为什么这么建立模型呢?这节主要不是讨论关系 关系这个会放到  第三节来讨论~~

    现在开始创建学生的实体类

    复制代码
    using System;
    using System.Collections.Generic;

    namespace ContosoUniversity.Models
    {
    public class Student
    {
    public int StudentID { get; set; }
    public string LastName { get; set; }
    public string FirstMidName { get; set; }
    public DateTime EnrollmentDate { get; set; }
    public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
    }
    复制代码

    在这里面 这个StudentID将被默认的设为主键  EF将会默认的给名字为ID的或者带ID的设置为主键

    Enrollments是一个导航属性  将做为外键    导航属性定义为virtual 以便于实现延迟加载 

      接下来 创建登记录入表(关系表)的实体类 

    复制代码
    using System;
    using System.Collections.Generic;

    namespace ContosoUniversity.Models
    {
    public class Enrollment
    {
    public int EnrollmentID { get; set; }
    public int CourseID { get; set; }
    public int StudentID { get; set; }
    public decimal? Grade { get; set; }
    public virtual Course Course { get; set; }
    public virtual Student Student { get; set; }
    }
    }
    复制代码

    这里面 我们的成绩是可空类型     学生实体有多个 Enrollment 而Enrollment有一个学生实体的导航属性 这里面 我们既有学生ID 又有学生实体属性 我们会担心 会不会生成两个呢StudentID?不用担心 EF很聪明 在关系表里 只有一个studentID

    接下来就是创建课程实体了

    复制代码
    using System;
    using System.Collections.Generic;

    namespace ContosoUniversity.Models
    {
    public class Course
    {
    public int CourseID { get; set; }
    public string Title { get; set; }
    public int Credits { get; set; }
    public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
    }
    复制代码

    OK了 实体创建好了 接下来 我们要创建一个 数据库上下文

    二.Creating the Database Context

    这个类主要是把上面创建的实体类包含再里面  指定哪些实体类包含在我们的数据模型中 还有 这个类可以指定我们的映射关系 还可以指定一些生成的约束关系总之 很有用的

    这里面 我们先创建一个DAL的文件夹 然后在下面新建一个类 叫做SchoolContext  并且继承DbContext

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data;
    using System.Data.Entity;
    using ContosoUniversity.Models;
    using System.Data.Entity.ModelConfiguration.Conventions;
    using System.Data.Entity.Infrastructure;



    namespace ContosoUniversity.DAL
    {
    public class SchoolContext:DbContext
    {
    private readonly static string CONNECTION_STRING = "name=WlfSys_EFCF_ConnString";


    public DbSet<Student> Students { get; set; }
    public DbSet<Enrollment> Enrollments { get; set; }
    public DbSet<Course> Courses { get; set; }

    public SchoolContext()
    : base(CONNECTION_STRING)//不写这个 默认的就是SchoolContext
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//移除复数表名的契约

    modelBuilder.Conventions.Remove<IncludeMetadataConvention>();//防止黑幕交易 要不然每次都要访问 EdmMetadata这个表




    /*

    可以删除的公约有:
    Namespace:System.Data.Entity.ModelConfiguration.Conventions.Edm
    • AssociationInverseDiscoveryConvention
    寻找导航上互相引用的类的属性,并将它们配置为逆属性的相同的关系。
    • ComplexTypeDiscoveryConvention
    寻找有没有主键的类型,并将它们配置为复杂类型。
    • DeclaredPropertyOrderingConvention
    确保每个实体的主要关键属性优先于其他属性。
    • ForeignKeyAssociationMultiplicityConvention
    配置是必需的还是可选的关系基于为空性外键属性,如果包含在类定义中。
    • IdKeyDiscoveryConvention
    查找名为 Id 或 <TypeName> Id 的属性,并将他们配置作为主键。
    • NavigationPropertyNameForeignKeyDiscoveryConvention
    使用外键关系,使用 <NavigationProperty> <PrimaryKeyProperty> 模式作为属性的外观。
    • OneToManyCascadeDeleteConvention
    交换机上层叠删除,所需的关系。
    • OneToOneConstraintIntroductionConvention
    将配置为一个: 一个关系的外键的主键。
    • PluralizingEntitySetNameConvention
    配置为多元化的类型名称的实体数据模型中的实体集的名称。
    • PrimaryKeyNameForeignKeyDiscoveryConvention
    使用外键关系,使用 <PrimaryKeyProperty> 模式作为属性的外观。
    • PropertyMaxLengthConvention
    配置所有的字符串和字节 [] 属性,默认情况下具有最大长度。
    • StoreGeneratedIdentityKeyConvention
    配置默认情况下将标识所有整数的主键。
    • TypeNameForeignKeyDiscoveryConvention
    使用外键关系,使用 <PrincipalTypeName> <PrimaryKeyProperty> 模式作为属性的外观。


    */

    }

    }
    }
    复制代码

    详细的解释下这里

     private readonly static string CONNECTION_STRING = "name=WlfSys_EFCF_ConnString";
     public SchoolContext()
    : base(CONNECTION_STRING)//不写这个 默认的就是SchoolContext
    {

    }

    上面这里是配置连接字符串  默认的就是SchoolContext 即你这个context的名字

    复制代码
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//移除复数表名的契约

    modelBuilder.Conventions.Remove<IncludeMetadataConvention>();//防止黑幕交易 要不然每次都要访问 EdmMetadata这个表

    复制代码

    再重写的这个方法里 我们可以移除一些契约  还可以配置数据库映射关系  常用的移除信息 都写在里面了

    三.设置连接字符串

     <connectionStrings>
    <add name="WlfSys_EFCF_ConnString"
    providerName="System.Data.SqlClient" connectionString="Data Source=.;Initial Catalog=WLFSchool;Integrated Security=True;Pooling=False" />
    </connectionStrings>

    我们的这个名字 和上面设置的一直~~(那个英文博客里用的是 SQL Server Compact database 但为了让项目贴近实际 我这里用SQL2005)

    四.数据库数据初始化

    在DAL下 新建一个类 SchoolInitializer  继承自 DropCreateDatabaseIfModelChanges<SchoolContext>  这个类主要实现 数据库数据初始化 方便测试~~

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;//记得引用命名空间
    using ContosoUniversity.Models;


    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 { Title = "Chemistry", Credits = 3, }, new Course { Title = "Microeconomics", Credits = 3, }, new Course { Title = "Macroeconomics", Credits = 3, }, new Course { Title = "Calculus", Credits = 4, }, new Course { Title = "Trigonometry", Credits = 4, }, new Course { Title = "Composition", Credits = 3, }, new Course { Title = "Literature", Credits = 4, } }; courses.ForEach(s => context.Courses.Add(s)); context.SaveChanges(); var enrollments = new List<Enrollment> { new Enrollment { StudentID = 1, CourseID = 1, Grade = 1 }, new Enrollment { StudentID = 1, CourseID = 2, Grade = 3 }, new Enrollment { StudentID = 1, CourseID = 3, Grade = 1 }, new Enrollment { StudentID = 2, CourseID = 4, Grade = 2 }, new Enrollment { StudentID = 2, CourseID = 5, Grade = 4 }, new Enrollment { StudentID = 2, CourseID = 6, Grade = 4 }, new Enrollment { StudentID = 3, CourseID = 1 }, new Enrollment { StudentID = 4, CourseID = 1, }, new Enrollment { StudentID = 4, CourseID = 2, Grade = 4 }, new Enrollment { StudentID = 5, CourseID = 3, Grade = 3 }, new Enrollment { StudentID = 6, CourseID = 4 }, new Enrollment { StudentID = 7, CourseID = 5, Grade = 2 }, }; enrollments.ForEach(s => context.Enrollments.Add(s)); context.SaveChanges(); } }}
    复制代码

    这样还没有完 还要再 Global.asax 下的Application_Start()加上如下代码

     Database.SetInitializer<SchoolContext>(new SchoolInitializer());


    五.创建控制器

     创建好后添加

        private SchoolContext db = new SchoolContext();

    再在Index方法下添加得到所有学生的方法

    public ViewResult Index()
    {
    return View(db.Students.ToList());
    }

    六.添加视图(小谈MVC的 DISPLAY)

    复制代码
    @model IEnumerable<ContosoUniversity.Models.Student>

    @{
    ViewBag.Title = "Students";
    }

    <h2>Students</h2>

    <p>
    @Html.ActionLink("Create New", "Create")
    </p>
    <table>
    <tr>
    <th></th>
    <th>Last Name</th>
    <th>First Name</th>
    <th>Enrollment Date</th>
    </tr>

    @foreach (var item in Model) {
    <tr>
    <td>
    @Html.ActionLink("Edit", "Edit", new { id=item.StudentID }) |
    @Html.ActionLink("Details", "Details", new { id=item.StudentID }) |
    @Html.ActionLink("Delete", "Delete", new { id=item.StudentID })
    </td>
    <td>
    @Html.DisplayFor(modelItem => item.LastName)
    </td>
    <td>
    @Html.DisplayFor(modelItem => item.FirstMidName)
    </td>
    <td>
    @Html.DisplayFor(modelItem => item.EnrollmentDate)
    </td>
    </tr>
    }

    </table>
    复制代码

    好了 视图添加完了 这里面 我们用了 Html.DisplayFor  刚看到这个时 总是不明白这个到底显示什么 还有实体类上 总是加上display(name="")这样的特性 但是又和这个没关系 让我很郁闷

    查了MSDN和相关资料 终于明白  Html.DisplayFor 可以算是显示模版 显示实体类的特性[DataType(DataType.Password)] 这样显示的就是密码框   而 display(name="")这样的特性  则是让 Html.LabelFor()去显示的  display的具体的 可以看下这个文章 介绍的不错 display模版详细介绍

    七.运行环境 查看结果

    大家一定很关心数据库的生成什么样子滴~~

    EdmMetadata 数据库记录个版本对照 可以不要 在契约里有删除~~用站长dudu的话 防止黑幕交易

    八.总结

    很简单的创建一个EF4.1 代码优先的小例子 没什么难度~~ 但还是认真的写了下来 好累哦

    本文章來源

    http://www.cnblogs.com/wlflovenet/archive/2011/07/24/2115171.html

  • 相关阅读:
    Mac下安装svn服务器
    php 当前日期加一天和指定日期加一天
    MariaDB与MySQL
    JS中判断null、undefined与NaN的方法
    PHP保留两位小数的几种方法
    jquery的cookie插件
    mysql(5.7以上)查询报错:ORDER BY clause is not in GROUP BY..this is incompatible with sql_mode=only_full_group_by
    MySQL数据的导出和导入
    qrCode二维码字符串长度太多压缩的问题
    解决 img 标签上下出现的间隙
  • 原文地址:https://www.cnblogs.com/sdya/p/3972256.html
Copyright © 2020-2023  润新知