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,里面放置两个模型实体(学生和课程):

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Hibernate Annotation几种关联映射 一对一(One-To-One) 使用@OneToOne注解建立实体Bean之间的一对一关联。一对一关联有三种情况:(1).关联的实体都共享同样的主键,(2).其中一个实体通过外键关联到另一个实体的主键(注意要模拟一对一关联必须在外键列上添加唯一约束),(3).通过关联来保存两个实体之间的连接关系(要模拟一对一关联必须在每一个外键上添加唯一约束)。 1.共享主键的一对一关联映射: @Entity @Table(name="Test_Body") public class Body { private Integer id; private Heart heart; @Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @OneToOne @PrimaryKeyJoinColumn public Heart getHeart() { return heart; } public void setHeart(Heart heart) { this.heart = heart; } } @Entity @Table(name="Test_Heart") public class Heart { private Integer id; @Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } 通过@PrimaryKeyJoinColumn批注定义了一对一关联 2.使用外键进行实体一对一关联: @Entity @Table(name="Test_Trousers") public class Trousers { @Id public Integer id; @OneToOne @JoinColumn(name = "zip_id") public TrousersZip zip; } @Entity @Table(name="Test_TrousersZip") public class TrousersZip { @Id public Integer id; @OneToOne(mappedBy = "zip") public Trousers trousers; } 上面的例子是指Trousers通过Trousers的外键列zip_id和TrousersZip关联,@JoinColumn批注定义了联接列,该批注和@Column批注有点类似,但是多了一个名为referencedColumnName的参数。该参数定义了所关联目标实体中的联接列,注意,当referencedColumnName关联到非主键列的时候,关联的目标类必须实现Serializable,还要注意的是所映像的属性对应单个列(否则映射无效) 一对一关联可能是双向的,在双向关联中,有且仅有一端作为主体(owner)端存在:主体端负责维护联接列(即更新),对于不需要维护这种关系的从则通过mappedNy属性进行声明。mappedBy的值指向主体的关联属性。例子中,mappedBy的值为zip。最后,不必也不能再在被关联端(ownedside)定义联接列了,因为已经在主体端声明了。 如果在主体没有声明@JoinColumn,系统自动进行处理:在主(owner table)中将创建联接列,列名为:主体的关联属性名+下划线+被关联端的主键列名。上面的例子中是zip_id,因为Trousers中的关联属性名为zip,TrousersZip的主键是id。 3.通过关联定义一对一关联 @Entity @Table(name="Test_People") public class People { @Id public Integer id; @OneToOne @JoinTable(name ="TestPeoplePassports", joinColumns =@JoinColumn(name="people_fk"), inverseJoinColumns =@JoinColumn(name="passport_fk") ) public Passport passport; } @Entity @Table(name="Test_Passport") public class Passport { @Id public Integer id; @OneToOne(mappedBy = "passport") public People people; } People通过名为TestPeoplePassports的关联和Passport关联。该关联拥有名为passport_fk的外键列,该外键指向Passport,该信息定义为inverseJoinColoumns的属性值,而people_fk外键列指向People,该信息定义为joinColumns的属性值。 这种关联可能是双向的,在双向关联中,有且仅有一端作为主体(owner)端存在:主体端负责维护联接列(即更新),对于不需要维护这种关系的从则通过mappedNy属性进行声明。mappedBy的值指向主体的关联属性。例子中,mappedBy的值为passport。最后,不必也不能再在被关联端(ownedside)定义联接列了,因为已经在主体端声明了。 以上是一对一关联的三种形式,下面介绍多对一关联。 多对一(Many-to-One) 使用@ManyToOne批注来实现多对一关联。 @ManyToOne批注有一个名为targetEntity的参数,该参数定义了目标实体名,通常不需要定义该参数,因为在大部分情况下默认值(关联关系的属性类型)就可以很好的满足需求了。不过下面这种情况下这个参数就显得有意义了:使用接口作为返回值而不是常见的实体。 @ManyToOne(targetEntity=CompanyImpl.class) @JoinColoumn(name=”COPM_ID”) Public Company getCompany(){ return company; } 多对一的配置方式有两种:(1)通过@JoinColoumn映像(2)通过关联的方式来映像 (1) 通过@JoinColoumn映射 SRD Framework中Company,Category例子: Company: @ManyToOne @JoinColumn(name = "CATEGORY_OPTION_ID") private Category category = null; Category: @DiscriminatorValue("Category") public class Category extends Option { } (2) 通过关联映射 通过@JoinTable批注定义关联,该关联包含了指回实体的外键(通过@JoinTable.joinColoumns)以及指向目标实体的外键(通过@JoinTable.inverseJoinColoumns) @Entity @Table(name="Test_TreeType") public class TreeType { private Integer id; private String name; private ForestType forestType; @ManyToOne(fetch = FetchType.LAZY) @JoinTable(name="Test_Tree_Forest", joinColumns = @JoinColumn(name="tree_id"), inverseJoinColumns = @JoinColumn(name="forest_id") ) public ForestType getForestType() {// forestType的getter,setter方法必须在这里,否则会出错 return forestType; } public void setForestType(ForestType forestType) { this.forestType = forestType; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @Entity @Table(name="Test_ForestType") public class ForestType { private Integer id; private String name; private Set<TreeType> trees; @OneToMany(mappedBy="forestType") public Set<TreeType> getTrees() {// trees的getter,setter方法必须在这里,否则会出错 return trees; } public void setTrees(Set<TreeType> trees) { this.trees = trees; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 一对多(One-to-Many) 使用@OneToMany批注可定义一对多关联,一对多关联可以是双向关联。 在EJB3规范中多对一这端几乎总是双向关联中的主体(owner)端,而一对多这端关联批注为@OneToMany(mappedBy...) @Entity Public class Troop{ @OneToMany(mappedBy=”troop”) Public Set<Soldier> getSoldiers(){ ...... } @Entity Public class Soldier{ @ManyToOne @JoinColumn(name=”troop_fk”) Public Troop getTroop(){ ...... } Troop通过troop属性和Soldier建立一对多的双向关联,在mappedBy端不必也不能再定义任何物理映射。 对于一对多的双向映射,如果要一对多这一端维护关联关系,你需要删除mappedBy元素并将多对一这端的@JoinColoumn的insertable和updatabel设置为false。这种方案不会得到什么明显的优化,而且还会增加一些附加的UPDATE语句。 单向: 通过在被拥有的实体端(owned entity)增加一个外键列来实现一对多单向关联是很少见的,也是不推荐的,建议通过一个联接实现这种关联(下面会讲到)。 @JoinColoumn批注来描述这种单向关联关系 @Entity Public class Customer{ @OneToMany @JoinColoumn(name=”CUST_ID”) Public Set<ticket> getTickets() { ...... } @Entity Public class Ticket{ ... } Customer通过CUST_ID列和Ticket建立了单向关联关系 通过关联处理单向关联: 通过联接处理单向一对多关联是首选方式,这种关联通过@JoinTable批注进行描述 @Entity Public class Trainer{ @OneToMany @JoinTable( name = "TrainedMonkeys", jonColumns = {@JoinColumn(name = "trainer_id")}, inverseJoinColumns = @JoinColumn(name = "monkey_id") ) public Set<Monkey> getTrainedMonkeys() { return trainedMonkeys; } ...... } @Entity public class Monkey { ...//no bidir } 上面这个例子中,Trainer通过TrainedMonkeys和Monkey建立了单向关联,其中外键trainer_id关联到Trainer(joinColoumn),而外键monkey_id关联到Monkey(inversejionColoumns) 默认处理机制: 通过联接来建立单向一对多关联不需要描述任何物理映像,名由以下三个部分组成:主(ownertable)名+从(the other side table)名,指向主的外键名:主名+下划线+主主键列名,指向从的外键名:主所对应实体的属性名+下划线+从主键列名,指向从的外键定义为唯一约束,用来示一对多的关联关系。 @Entity public class Trainer{ @OneToMany Public Set<Tiger> getTrainedTigers(){ ... ... } @Entity public class Tiger{ .. ..//no bidir } 上面这个例子中,Trainer和Tiger通过联接Trainer_Tiger建立单向关联关系,其中外键trainer_id关联到Trainer,而外键trainedTigers_id关联到Tiger 多对多(Many-to-Many) 使用@ManyToMany批注可定义多对多关联,同时,你也许要通过批注@JoinTable描述关联关联条件。如果是双向关联,其中一段必须定义为Owner,另一端必须定义为inverse(在对关联进行更新操作时这一端将被忽略) @Entity() public class Employer implements Serializable { private Integer id; private Collection employees; @ManyToMany( targetEntity = org.hibernate.test.annotations.manytomany.Employee.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) @JoinTable( name = "EMPLOYER_EMPLOYEE", joinColumns = {@JoinColumn(name = "EMPER_ID")}, inverseJoinColumns = {@JoinColumn(name = "EMPEE_ID")} ) public Collection getEmployees() { return employees; } ... } @Entity() public class Employee implements Serializable { @ManyToMany( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "employees" targetEntity = Employer.class ) public Collection<Employer> getEmployers() { return employers; } .. .. } @JoinTable批注定义了联接名,联接列数组,以及invers联接列数组,后者是关联关联到Employee主键的列(the “other side”)。 被关联端不必也不能描述物理映射:只需要一个简单的mappedBy参数,该参数包含了主体端的属性名,这样就绑定了双方的关系。 默认值: 和其它许多批注一样,在多对多关联中很多值是自动生成,党双向多对多关联中没有定义任何物理映射时,Hibernate根据以下规则生成相应的值,关联名:主名+下划线+从名,关联到主的外键名:主名+下划线+主中的主键列名,关联到从的外键名:主中用于关联的属性名+下划线+从的主键列名,以上规则对于双向一对多关联同样一样。 以上是整理的一点简单的几种映射,可参考EJB3.pdf中P111——P131,hibernate_annotation.pdf 第二章 在这里没有具体的例子,有很多内容还需要仔细查看文档。
.NET Framework 是由 Microsoft 开发的一种全面且一致的编程模型,用于生成具有视觉震撼力的用户体验、无缝的安全通信和对一系列业务流程进行建模的能力的应用程序。 .NET Framework 4 将与旧的 Framework 版本并行工作。 默认情况下,基于早期版本的 Framework 的应用程序将继续在目标版本上运行。 Microsoft .NET Framework 4 提供了以下新功能和改进: 公共语言运行时 (CLR) 和基类库 (BCL) 的改进 性能改进,包括更好的多核心支持、后台垃圾回收和服务器上的探查器附加。 新的内存映射文件和数字类型。 更轻松的调试,包括转储调试、Watson 小型转储、64 位的混合模式调试和代码协定。 有关 CLR 和 BCL 的增强功能的完整列,请转到此处。 Visual Basic 和 C# 语言中的创新,例如 lambda 语句、隐式行继续符、动态调度和命名/可选参数。 数据访问和建模的改进 利用 Entity Framework,开发人员可使用 .NET 对象和语言集成查询 (LINQ) 对关系数据库进行编程。 它具有多项新功能,包括持久性忽略和 POCO 支持、外键关联、延迟加载、测试驱动开发支持、模型中的函数和新的 LINQ 运算符。 其他功能包括:带自跟踪实体的更好的 n 层支持、使用 T4 模板的可自定义的代码生成、模型首次开发、改进的设计器体验、更好的性能以及实体集的复数形式。 有关更多信息,请转到此处。 WCF 数据服务是 .NET Framework 的一个组件,可以利用此服务创建基于 REST 的服务和应用程序,以便使用开放式数据协议 (OData) 在 Web 上公开和使用数据。 WCF 数据服务具有多项新功能,包括增强的 BLOB 支持、数据绑定、行计数、源自定义、投影和请求管道改进。 当前与 Microsoft Office 2010 的内置集成可将 Microsoft Office SharePoint Server 数据作为一个 OData 源公开,并使用 WCF 数据服务客户端库访问该数据源。 有关更多信息,请转到此处。 ASP.NET 的增强功能 对 HTML、元素 ID 和自定义 CSS 的更多控制,通过这些控制可更轻松地创建符合标准且 SEO 友好的 Web 窗体。 新的动态数据功能,包括新的查询筛选器、实体模板、对 Entity Framework 4 的更丰富的支持以及可轻松应用于现有 Web 窗体的验证和模板化功能。 针对新的 AJAX 库改进的 Web 窗体支持,包括对内容传递网络 (CDN) 的内置支持。 有关 ASP.NET 增强功能的完整列,请转到此处。 Windows Presentation Foundation (WPF) 的改进 添加对 Windows 7 多点触控、功能区控件和任务栏扩展性功能的支持。 添加了对 Surface 2.0 SDK 的支持。 新的业务线控件,包括图控件、智能编辑、数据网格以及其他用于改进生成以数据为中心的应用程序的开发人员体验的控件。 性能和伸缩性的改进。 文本清晰度、布局像素对齐、本地化和互操作性的可视化改进。 有关 WPF 的增强功能的完整列,请转到此处。 Windows 工作流 (WF) 的改进,利用这些改进,开发人员能够更好地承载工作流并与其进行交互。 这些改进包括:改进的活动编程模型、改进的设计器体验、新的流程图建模样式、展开的活动面板、工作流规则集成和新的消息相关功能。 .NET Framework 4 还显著提高了基于 WF 的工作流的性能。 有关 WF 的增强功能的完整列,请转到此处。 Windows Communication Foundation (WCF) 的改进,例如对 WCF 工作流服务的支持(可启用带消息传递活动的工作流程序)和相关支持。 此外,.NET Framework 4 还提供了新的 WCF 功能,如服务发现、路由服务、REST 支持、诊断和性能。 有关 WCF 的增强功能的完整列,请转到此处。 创新的新并行编程功能,例如并行循环支持、任务并行库 (TPL)、并行 LINQ (PLINQ) 和协调数据结构(可让开发人员利用多核处理器)。
关于EF6的正式书籍很少,这个文章是国内翻译整理出来的,共46个小节。适合循序渐进的学习。 第1部分 开始使用实体框架之历史和框架简述 第2部分 开始使用实体框架之使用介绍 第3部分 实体数据建模基础之创建一个简单的模型 第4部分 实体数据建模基础之从已存在的数据库创建模型 第5部分 实体数据建模基础之有载荷和无载荷的多对多关系建模 第6部分 实体数据建模基础之使用Code First建模自引用关系 第7部分 实体数据建模基础之拆分实体到多以及拆分到多实体 第8部分 实体数据建模基础之继承关系映射TPT 第9部分 实体数据建模基础之继承关系映射TPH 第10部分 实体数据建模基础之两实体间Is-a和Has-a关系建模、嵌入值映射 第11部分 查询之异步查询 第12部分 查询之使用SQL语句 第13部分 查询之使用Entity SQL 第14部分 查询之查询中设置默认值和存储过程返回多结果集 第15部分 查询之与列值比较和过滤关联实体 第16部分 查询之左连接和在TPH中通过派生类排序 第17部分 查询之分页、过滤和使用DateTime中的日期部分分组 第18部分 查询之结果集扁平化和多属性分组 第19部分 查询之使用位操作和多属性连接(join) 第20部分 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例 第21部分 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑 第22部分 加载实体和导航属性之延迟加载 第23部分 加载实体和导航属性之预先加载与Find()方法 第24部分 加载实体和导航属性之查询内存对象 第25部分 加载实体和导航属性之加载完整的对象图和派生类型上的导航属性 第26部分 加载实体和导航属性之延缓加载关联实体和在别的LINQ查询操作中使用Include()方法 第27部分 加载实体和导航属性之关联实体过滤、排序、执行聚合操作 第28部分 加载实体和导航属性之测试实体是否加载与显式加载关联实体 第29部分 加载实体和导航属性之过滤预先加载的实体集合和修改外键关联 第30部分 继承与建模高级应用之多对多关联 第31部分 继承与建模高级应用之自引用关联 第32部分 继承与建模高级应用之TPH与TPT (1) 第33部分 继承与建模高级应用之TPH与TPT (2) 第34部分 继承与建模高级应用之多条件与QueryView 第35部分 继承与建模高级应用之TPH继承映射中使用复合条件 第36部分 继承与建模高级应用之TPC继承映射 第37部分 继承与建模高级应用之独立关联与外键关联 第38部分 使用对象服务之动态创建连接字符串和从数据库读取模型 第39部分 使用对象服务之配置模型和使用单复数服务 第40部分 使用对象服务之从跟踪器中获取实体与从命令行生成模型(想解决EF第一次查询慢的,请阅读) 第41部分 使用对象服务之标识关系中使用依赖实体与异步查询保存 第42部分 POCO之使用POCO 第43部分 POCO之使用POCO加载实体 第44部分 POCO之POCO中使用值对象和对象变更通知 第45部分 POCO之获取原始对象与手工同步对象图和变化跟踪器 第46部分 POCO之领域对象测试和仓储测试
### 回答1: Entity Framework是由微软开发的一种对象关系映射(ORM)框架,用于在应用程序和数据库之间建立连接和交互。它提供了一种简化的方式来操作数据库,减少了开发人员编写繁琐的数据库代码的工作量。 Entity Framework的官方中文教程提供了详细的指导和示例,帮助开发人员快速入门并深入理解该框架。教程覆盖了从基本概念到高级主题的广泛内容,确保开发人员能够全面了解和正确使用Entity Framework。 在教程中,您将学习如何创建实体数据模型,定义实体类和属性,并使用Code First或Database First方法生成数据库架构。您还将了解如何执行常见的数据操作,如插入、更新和删除数据,以及高级查询和过滤技术。 该教程还介绍了如何使用LINQ查询语言与Entity Framework集成,以及如何配置和管理实体关系、继承和导航属性等。此外,教程还包括了性能优化、事务处理和并发控制等方面的指导,帮助您运用Entity Framework的最佳实践。 无论您是初学者还是有经验的开发人员,通过Entity Framework官方中文教程,您将能够更高效、更轻松地利用该框架来构建稳健的应用程序。掌握Entity Framework的知识将使您能够更好地理解和操作应用程序中的数据,提高开发效率,减少代码量,并提供更好的可维护性和可扩展性。 ### 回答2: Entity Framework是微软推出的开源ORM(对象关系映射)框架,用于简化开发人员在应用程序中访问和操作数据库的过程。它允许开发人员通过使用面向对象的方法来处理数据库操作,而无需关注底层的数据库细节。 Entity Framework官方中文教程提供了针对初学者和有经验的开发人员的详细指导,帮助他们快速上手并使用Entity Framework进行开发。教程主要涵盖以下内容: 1. 环境准备:教程开始之前,首先介绍了Entity Framework的基本要求和安装步骤。它提供了逐步的说明,使读者能够轻松地配置和准备开发环境。 2. 数据模型:教程介绍了如何使用Entity Framework的Code First方法来创建和管理数据库的数据模型。它详细解释了如何定义实体类以及如何配置数据库关系和约束。 3. 数据访问:教程演示了如何通过Entity Framework执行常见的数据库操作,如插入、更新和删除数据。它还介绍了如何使用LINQ(Language Integrated Query)查询数据,以及如何使用存储过程和原始SQL查询。 4. 数据迁移:教程解释了如何使用Entity Framework的迁移工具来处理数据模型的更改和版本管理。它指导开发人员如何创建和应用迁移脚本,以便无缝地升级和更新数据库结构。 5. 性能优化:教程提供了一些建议和技巧,帮助开发人员优化Entity Framework应用程序的性能。它讨论了缓存、批量操作、延迟加载等性能改进方法,并解释了如何使用“Eager Loading”和“Explicit Loading”来提高查询性能。 总的来说,Entity Framework官方中文教程是一个全面而易于理解的资源,适用于所有层次的开发人员。无论是初学者还是有经验的开发人员,都可以通过这个教程深入了解Entity Framework的工作原理和最佳实践,并用它来简化和加速自己的数据库开发工作。 ### 回答3: Entity Framework是微软推出的一个对象关系映射(ORM)框架,用于简化与数据库的交互,并提供面向对象的方式进行数据操作。Entity Framework官方中文教程是微软提供的针对该框架的中文教学资料。 这个教程将帮助开发人员快速了解和掌握Entity Framework的基本概念、架构和使用方法。教程内容包括如何创建数据模型、执行数据查询、进行数据插入、更新和删除操作等。同时,教程还介绍了如何通过Code First、Database First和Model First等不同的开发方法来创建和管理数据模型。 在教程中,会提供具体的示例代码和详细的解释,以帮助开发者更好地理解框架的使用方式。通过按照教程的步骤进行实践,开发人员可以快速上手,并且能够在实际项目中应用Entity Framework来提高开发效率。 此外,教程还涵盖了一些高级主题,包括如何进行数据关联、使用事务、进行性能优化和使用存储过程等。这些内容可以帮助开发人员更深入地了解Entity Framework,并在实际应用中解决一些复杂的数据操作需求。 总而言之,Entity Framework官方中文教程是一个全面且系统的教学资源,对于想要学习和使用Entity Framework框架的开发人员来说,是一个不可或缺的参考资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈极简

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值