`
阿尔萨斯
  • 浏览: 4208422 次
社区版块
存档分类
最新评论

Entity Framework多对多关联映射的实现

 
阅读更多

Entity Framework是微软官方提供的一个ORM解决方案,它有纯正的血统,比NHibernate更容易使用并且与现有其它官方框架配合更加密切。

时代不断的在发展变化,记得10年前还是ADO(配合ASP)的天下,后来微软推出了ADO.NET,再后来推出了ADO.NET Entity Framework,可见微软在.NET与数据库交互领域的作为。

下面我将以Entity Framework(简称EF)来演示一下在C#当中如何使用好这个非常“爽”的ORM工具。我们以大家比较熟悉的模型—学生和课程的多对多的关系(学生可以选择多门课程、课程有可能有多个学生选择)来进行演示。

第一步,建立一个控制台应用程序,起名为CodeFirstEF。我们简单一点,尽量不参杂到其它技术来进行演示,将学习难度降低到最低。

建立一个控制台应用程序没有什么好说的,这里想简单的提一下,使用EF有3种常用的模型,Database-First(数据库优先)、Model-First(模型优先)、Code-First(代码优先)。其中前两种,数据库优先和模型优先是比较简单的两种模型。可以直接通过VS工具连接数据库自动生成与数据库交互的DbContext对象,这种模式有点像我们老早用过的不写一行代码就能自动绑定GridView一样(虽然有点夸张),虽然极大的提高了使用效率,但是灵活度欠缺。因此这篇博客,主要演示代码优先模型,所以起名为CodeFirstEF。

第二步,在CodeFirstEF中建立一个文件夹Entity,里面放置两个模型实体(学生和课程):

namespace CodeFirstEF.Entity
{
    public enum Gender { Female, Male }

    public class Student
    {
        [Key]
        [DatabaseGeneratedAttribute(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
        public int StudentId { get; set; }
        public string StudentName { get; set; }
        public Gender Gender { get; set; }
        public DateTime? BirthDay { get; set; }

        public virtual ICollection<Subject> Subjects { get; set; }
    }
}
学生类上面有个枚举,用以区别性别。

namespace CodeFirstEF.Entity
{
    public class Subject
    {
        [Key]
        [DatabaseGeneratedAttribute(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
        public int SubjectId { get; set; }
        public string SubjectName { get; set; }

        public virtual ICollection<Student> Students { get; set; }
    }
}
课程和学生类中都有两个虚属性,分别表示学生的课程以及课程有哪些学生。

第三步,添加EntityFramework支持。

两个Entity建好了,下面关键的要添加对EF的引用,这里介绍一个强大的工具NuGet程序包。我们右键点击控制台项目CodeFirstEF,选择管理NuGet程序包,打开下列弹出界面,选择联机,找到EntityFramework。


选择安装EntityFramework。


下载好EntityFramework会弹出窗口。


选择我接受,很快就会装好,装好后如下所示。


点击关闭。这时我们已经为我们的项目添加了EntityFramework支持,可以看到版本号为6,这是目前的最新版本。

第四步,在CodeFirstEF控制台项目下建立一个文件夹DAL,并创建一个数据库操作类DataContext。

namespace CodeFirstEF.DAL
{
    public class DataContext : DbContext
    {
        public DataContext(string connectionName) : base(connectionName) { }

        public DbSet<Student> Students { get; set; }
        public DbSet<Subject> Subjects { get; set; }
    }
}
它继承自DbContext,需要引用命名空间using System.Data.Entity。构造函数DbContext有一个参数connectionName,它是用于连接数据库的名称。这时我们切换到App.Config配置文件下,添加connectionStrings节点配置,将数据库连接的配置添加进去。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="codeFirstDb" connectionString="Data Source=.;uid=sa;pwd=123456;Database=CodeFirstDb;" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>
可以看到里面的codeFirstDb。

好了,这时候让我们看一下整个项目的结构。


第五步,在Program.cs的Main方法中写入测试代码。

namespace CodeFirstEF
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var db = new DataContext("codeFirstDb"))
            {
                //添加学生guwei4037
                if (!db.Students.Any(x => x.StudentName == "guwei4037"))
                {
                    db.Students.Add(new Student()
                    {
                        StudentName = "guwei4037",
                        Gender = Gender.Male,
                        BirthDay = new DateTime(1984, 11, 25),
                    });
                }

                //添加课程
                if (!db.Subjects.Any(x => x.SubjectName == "English" || x.SubjectName == "Mathmatics" || x.SubjectName == "Computer"))
                {
                    db.Subjects.AddRange(new Subject[] 
                    {
                        new Subject()
                        {
                            SubjectName="English",
                        },
                        new Subject()
                        {
                            SubjectName="Mathmatics",
                        },
                        new Subject()
                        {
                            SubjectName="Computer",
                        }
                    });
                }

                //找到guwei4037这个学生
                Student student = db.Students.FirstOrDefault(x => x.StudentName == "guwei4037");

                //找到数学和英语这两门课程
                List<Subject> subjects = db.Subjects.Where(x => x.SubjectName == "Mathmatics" || x.SubjectName == "English").ToList();

                //给学生添加课程
                foreach (Subject subject in subjects)
                {
                    student.Subjects.Add(subject);
                }

                //让课程知道有哪些学生选择了它
                foreach (Subject subject in subjects)
                {
                    subject.Students.Add(student);
                }

                //删除guwei4037这个学生其中的数学这门课程
                student.Subjects.Remove(db.Subjects.FirstOrDefault(x => x.SubjectName == "Mathmatics"));

                //保存上述操作的结果
                db.SaveChanges();
            }
        }
    }
}
很简单,注释也很清晰。

运行一下整个控制台项目,没有报错说明程序运行成功了。我们进数据库查看一下运行的情况。

这里我们也可以利用VS工具来查看,无须打开SQL Server。






我们看到,EF替我们自动创建了数据库CodeFirstDb,并且为我们创建了一张中间表,而且将数据都插入到了相应表中。

怎么样,EF相当强大吧?而且非常简单好用,让你写代码有非常“爽”的感觉。真正的面向对象编程就是这么简单,不用再学习额外的SQL编程了。


分享到:
评论

相关推荐

    Entity Framework 6 Recipes(中文word翻译版)

    第30部分 继承与建模高级应用之多对多关联 第31部分 继承与建模高级应用之自引用关联 第32部分 继承与建模高级应用之TPH与TPT (1) 第33部分 继承与建模高级应用之TPH与TPT (2) 第34部分 继承与建模高级应用之多条件...

    Hibernate_Annotation关联映射

    通过在被拥有的实体端(owned entity)增加一个外键列来实现一对多单向关联是很少见的,也是不推荐的,建议通过一个联接表来实现这种关联(下面会讲到)。 @JoinColoumn批注来描述这种单向关联关系 @Entity Public class...

    EntityFramework模型在领域驱动设计界定上下文中的应用

    在使用EntityFramework(以下简称EF)来定义模型(Model)时,开发人员往往喜欢把应用程序中的所有模型对象都一股脑地塞进一个模型中。这种开发习惯估计是源于DatabaseFirst的开发方式,在这种方式下,开发人员可以...

    Microsoft .NET Framework 4

    新的动态数据功能,包括新的查询筛选器、实体模板、对 Entity Framework 4 的更丰富的支持以及可轻松应用于现有 Web 窗体的验证和模板化功能。 针对新的 AJAX 库改进的 Web 窗体支持,包括对内容传递网络 (CDN) 的...

    Python 手写ORM-我的一个数据库访问工具

    ORM框架可以化解SQL语句的复杂性,对数据库访问进行对象化,可以减少程序的代码量,并且能大大减少重复性代码学过.NET语言的同学都知道在.NET平台下基于LINQ的EntityFramework的ORM框架吧。在我们开发系统时,一般都有...

    GroveKit12Beta

    Grove Develop Component Kit 包括 Grove Develop Component 和 Grove Tool Kit两部分;... Grove Tool Kit最大的特点在于可以通过工具本身调试,关联多表之间的关系,并生成多表查询的映射实体或XML映射描述。

    Grove[.NET组件开发包]

    软件介绍: Grove Develop Component Kit 包括 Grove Develop Component 和 Grove Tool Kit两... Grove Tool Kit最大的特点在于可以通过工具本身调试,关联多表之间的关系,并生成多表查询的映射实体或XML映射描述。

    efcore:EF Core是.NET的现代对象数据库映射器。 它支持LINQ查询,更改跟踪,更新和模式迁移

    资料库 该存储库是以下项目的所在地。 这些项目由维护,并根据获得。 实体框架核心 EF Core是用于.NET的现代对象数据库映射器。 它支持LINQ查询,更改...dotnet add package Microsoft.EntityFrameworkCore.SqlServer

    Grove[.net开发组件包]

    Grove Develop Component Kit ... Grove Tool Kit最大的特点在于可以通过工具本身调试,关联多表之间的关系,并生成多表查询的映射实体或XML映射描述. 安装说明: 1.解压zip包,执行安装 2.执行桌面上的Grove Install

    Snake.net框架

    2. Snake.Net通过DataSet配置映射关系(数据表、字段,关键字,外部关键字,关联关系等),对象的映射关系将通过元数据适配器转化为DataSet构架。因而可以使用多种方式进行关系映射(如DataSet Schema文件, ...

    framword4.5

    新的动态数据功能,包括新的查询筛选器、实体模板、对 Entity Framework 4 的更丰富的支持以及可轻松应用于现有 Web 窗体的验证和模板化功能。 针对新的 AJAX 库改进的 Web 窗体支持,包括对内容传递网络 (CDN) 的...

    ssh(structs,spring,hibernate)框架中的上传下载

    其实现类是apache的BasicDataSource,第11~25行定义了Hibernate的会话工厂,会话工厂类用Spring提供的LocalSessionFactoryBean维护,它注入了数据源和资源映射文件,此外还通过一些键值对设置了Hibernate所需的属性...

    mvc3高级编程英文版

    型在控制器和视图之间传递信息,以及如何在Entity Framework 4.1 上集成数据库和模型。 第5 章深入讲解编辑场合,解释ASP.NET MVC 处理表单的方式。您将从本章中学习 到如何使用HTML 辅助方法精简视图。 第6 章介绍...

    客户关系管理系统框架搭建(二)

    * cn.itcast.crm.domain:放置的是po类、po类和数据库表关联的映射文件 * cn.itcast.crm.service:业务层的接口 * cn.itcast.crm.service.impl:业务层的接口的实现类 * cn.itcast.crm.web.action:struts2的...

    超级有影响力霸气的Java面试题大全文档

    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 13、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 14、...

    asp.net知识库

    在ASP.Net中两种利用CSS实现多界面的方法 如何在客户端调用服务端代码 页面一postback,它就显示页面的最顶端,怎样让它定位在某一位置? 如何保证页面刷新后的滚动条位置 清除网页历史记录,屏蔽后退按钮! 如何传值...

    java 面试题 总结

    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 10、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 11、HashMap...

Global site tag (gtag.js) - Google Analytics