实体间的关系,简单来说无非就是一对一、一对多、多对多,根据方向性来说又分为双向和单向。Code First在实体关系上有以下约定:
1. 两个实体,如果一个实体包含一个引用属性,另一个实体包含一个集合属性,Code First默认约定它们为一对多关系。
2. 两个实体,如果只有一个实体包含一个导航属性或一个集合属性,Code First也默认约定它们是一对多关系。
3. 两个实体分别包含一个集合属性,Code First默认约定它们为多对多关系。
4. 两个实体分别包含一个引用属性,Code First默认约定它们为一对一关系。
5. 在一对一关系情况下,需要提供给Code First额外的信息,以确定它们的主从关系。
6. 在实体中定义一个外键属性,Code First使用属性是否为空来确定关系是必须还是可选。
一、一对一
在Code First中,一对一关系总是需要配置,因为两个实体都包含有一个引用属性,无法确定它们的主从关系。
配置一对一关系常用的方法:
HasRequired ,HasOptional ,WithOptional ,WithRequiredPrincipal,WithRequiredDependent
下面是用到的类:
public class Person { public int PersonId { get; set; } public int SocialSecurityNumber { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public byte[] RowVersion { get; set; } public PersonPhoto Photo { get; set; } } public class PersonPhoto { public int PersonId { get; set; } public byte[] Photo { get; set; } public string Caption { get; set; } public Person PhotoOf { get; set; } }
因为Photo是具体人的,所以PersonPhoto使用PersonId作为主键。
下面是一对一关系配置的几种情况:
1.PersonPhoto必须属于一个Person,但是Person不一定有PersonPhoto,这种关系是1:0..1,此种情况下Person是一定存在的,所以它是主从关系主的一方。
1: HasRequired(t => t.PhotoOf).WithOptional(t => t.Photo);
或
1: HasOptional(t => t.Photo).WithRequired(t => t.PhotoOf);
2.PersonPhoto必须属于一个Person,Person也必须有PersonPhoto,这种关系式1:1,此种情况下,两个都一定存在,要确定主从关系,需要使用WithRequiredPrincipal或WithRequiredDependent。
1: HasRequired(t => t.PhotoOf).WithRequiredDependent(t => t.Photo);
或
1: HasRequired(t => t.Photo).WithRequiredPrincipal(t => t.PhotoOf);
上述两种情况都是真实存在的,不真实存在的就不说了。
下面配置一对一关系贴出Demo:
//配置Person public class PersonConfiguration : EntityTypeConfiguration<Person> { public PersonConfiguration() { //主键 HasKey(t => t.PersonId); //并发检查 Property(t => t.SocialSecurityNumber).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).IsConcurrencyToken(); //长度50 不为空 Property(t => t.FirstName).IsRequired().HasMaxLength(50); //长度50 不为空 Property(t => t.LastName).IsRequired().HasMaxLength(50); //并发检查 Property(t => t.RowVersion).IsRowVersion(); //HasRequired(t => t.Photo).WithRequiredPrincipal(t => t.PhotoOf); //HasOptional(t => t.Photo).WithRequired(t => t.PhotoOf); } } //配置PersonPhoto public class PersonPhotoConfiguration : EntityTypeConfiguration<PersonPhoto> { public PersonPhotoConfiguration() { //主键 HasKey(t => t.PersonId); //长度50 Property(t => t.Caption).HasMaxLength(50); //必须从属于Person HasRequired(t => t.PhotoOf).WithRequiredDependent(t => t.Photo); } } public class BreakAwayContext : DbContext { public DbSet<Person> People { get; set; } public DbSet<PersonPhoto> Photos { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PersonConfiguration()); modelBuilder.Configurations.Add(new PersonPhotoConfiguration()); base.OnModelCreating(modelBuilder); } } public class Initializer : DropCreateDatabaseAlways<BreakAwayContext> { public Initializer() { } //创建数据库时 Seed数据 protected override void Seed(BreakAwayContext context) { context.People.Add(new Person() { FirstName = "E", LastName = "F", SocialSecurityNumber = 123456, Photo = new PersonPhoto() { Caption = "这是照片", Photo = new byte[] { } } }); context.SaveChanges(); }
二、一对多
下面是用到的类:
public class Blog { public Blog() { Posts = new List<Post>(); } public int Id { get; set; } public DateTime Creationdate { get; set; } public string ShortDescription { get; set; } public string Title { get; set; } public List<Post> Posts { get; set; } } public class Post { public int Id { get; set; } public string Title { get; set; } public string Content { get; set; } public DateTime PostedDate { get; set; } public Nullable<int> BlogId { get; set; } public virtual Blog Blog { get; set; } public int PrimaryAuthorId { get; set; } public virtual Author PrimaryAuthor { get; set; } public Nullable<int> SecondaryAuthorId { get; set; } public virtual Author SecondaryAuthor { get; set; } } public class Author { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } //个人简历 public string Bio { get; set; } public List<Post> PrimaryAuthorFor { get; set; } public List<Post> SecondaryAuthorFor { get; set; } }
配置一对多关系常用的方法有:
HasOptional ,HasRequired ,HasMany
Has方法后面往往跟着With方法
WithOptional ,WithRequired ,WithMany
下面配置一对多的几种情况:
1.Post一定归属于一个Blog,这种关系是1:n。
1: HasMany(x => x.Posts).WithRequired(x =>x.Blog)
或
1: HasRequired(x => x.Blog).WithMany(x => x.Posts)
2.Post可以单独存在,不用归属于Blog,这种关系是0..1:n。
1: HasMany(x => x.Posts).WithOptional(x => x.Blog)
或
1: HasOptional(x => x.Blog).WithMany(x => x.Posts)
设置外键
外键的默认约定:
[Target Type Key Name], [Target Type Name] + [Target Type Key Name], or [Navigation
Property Name] + [Target Type Key Name]
本例中,匹配的是[Target Type Name] + [Target Type Key Name],目标类型是Blog,目标类型主键是Id,加起来就是BlogId。下面使用Fluent API显示设置外键:
1: HasMany(x => x.Posts).WithOptional(x => x.Blog).HasForeignKey(x => x.BlogId)
设置级联删除
1: HasMany(x => x.Posts).WithOptional(x => x.Blog).HasForeignKey(x => x.BlogId).WillCascadeOnDelete();
反转属性
在Post实体中,有两个属性:PrimaryAuthor和SecondaryAuthor,第一作者和第二作者。在Author中有两个集合属性,Code First默认不能确定哪个集合属性和Post中的导航属性相匹配。使用Fluent API配置反转属性,如下:
1: HasRequired(t => t.PrimaryAuthor).WithMany(t => t.PrimaryAuthorFor);
2: HasOptional(t => t.SecondaryAuthor).WithMany(t => t.SecondaryAuthorFor);
下面是配置一对多关系的Demo
public class BlogConfiguratioin : EntityTypeConfiguration<Blog> { public BlogConfiguratioin() { ToTable("Blogs"); HasKey(t => t.Id); Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(t => t.Title).IsRequired().HasMaxLength(250); Property(t => t.Creationdate).HasColumnName("CreationDate").IsRequired(); Property(t => t.ShortDescription).HasColumnType("Text").IsMaxLength().IsOptional().HasColumnName("Description"); //配置Blog和Post的一对多关系,Blog对Post是可选的,外键BlogId,并设置为级联删除 HasMany(t => t.Posts).WithOptional(t => t.Blog).HasForeignKey(t => t.BlogId).WillCascadeOnDelete(); } } public class PostConfiguration : EntityTypeConfiguration<Post> { public PostConfiguration() { ToTable("Posts"); HasKey(t => t.Id); Property(t => t.Id).HasColumnName("PostId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(t => t.Content).HasColumnName("Body").IsMaxLength(); Property(t => t.PostedDate).HasColumnName("PostedDate"); Property(t => t.Title).HasColumnName("Title").IsMaxLength(); //配置反转属性,集合属性PrimaryAuthorFor匹配PrimaryAuthor HasRequired(t => t.PrimaryAuthor).WithMany(t => t.PrimaryAuthorFor); //配置反转属性,集合属性SecondaryAuthorFor匹配SecondaryAuthor HasOptional(t => t.SecondaryAuthor).WithMany(t => t.SecondaryAuthorFor); } } public class AuthorConfiguration : EntityTypeConfiguration<Author> { public AuthorConfiguration() { ToTable("Authors"); HasKey(t => t.Id).Property(t => t.Id).HasColumnName("AuthorId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(t => t.Name).IsRequired().HasMaxLength(50); Property(t => t.Email).IsRequired().HasMaxLength(50); Property(t => t.Bio).HasMaxLength(1000); } } public class BreakAwayContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } public DbSet<Author> Authors { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new BlogConfiguratioin()); modelBuilder.Configurations.Add(new PostConfiguration()); modelBuilder.Configurations.Add(new AuthorConfiguration()); base.OnModelCreating(modelBuilder); } } public class Initializer : DropCreateDatabaseAlways<BreakAwayContext> { public Initializer() { } protected override void Seed(BreakAwayContext context) { var primaryAuthor = new Author() { Name = "张三", Email = "zhangsan@126.com", Bio = "张三的简历" }; var secondaryAuthor = new Author() { Name = "李四", Email = "lisi@126.com", Bio = "李四的简历" }; var blog = new Blog() { Title = "EF", ShortDescription = "关于EF的博客", Creationdate = DateTime.Now }; blog.Posts.Add(new Post() { Title = "配置关系", PostedDate = DateTime.Now, Content = "这是Post的内容", PrimaryAuthor = primaryAuthor, SecondaryAuthor = secondaryAuthor }); context.Blogs.Add(blog); context.SaveChanges(); }
三、多对多
下面是配置多对多关系用到的类,跟一对多差不多,只不过Post和Author的关系变成多对多的了。
public class Post { public int Id { get; set; } public string Title { get; set; } public string Content { get; set; } public DateTime PostedDate { get; set; } public virtual List<Author> Authors { get; set; } } public class Author { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } //个人简历 public string Bio { get; set; } public virtual List<Post> Posts { get; set; } }
一篇文章有多个作者,一个作者著有多篇文章。
配置多对多关系使用HasMany和WithMany方法,可以使用Map配置生成关联表的名字。
下面是配置多对多关系的Demo:
public class PostConfiguration : EntityTypeConfiguration<Post> { public PostConfiguration() { ToTable("Posts"); HasKey(t => t.Id); Property(t => t.Id).HasColumnName("PostId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(t => t.Content).HasColumnName("Body").IsMaxLength(); Property(t => t.PostedDate).HasColumnName("PostedDate"); Property(t => t.Title).HasColumnName("Title").IsMaxLength(); //配置多对多关系 ToTable 配置生成的关联表名字 MapLeftKey默认表示调用HasMany的实体的主键 //本例中如果不使用MapLeftKey默认生成Post_Id HasMany(t => t.Authors).WithMany(t => t.Posts).Map(m => { m.ToTable("PostAuthor"); m.MapLeftKey("PostId"); m.MapRightKey("AuthorId"); }); } } public class AuthorConfiguration : EntityTypeConfiguration<Author> { public AuthorConfiguration() { ToTable("Authors"); HasKey(t => t.Id); Property(t => t.Id).HasColumnName("AuthorId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); Property(t => t.Bio).HasColumnType("Text").IsMaxLength(); Property(t => t.Email).HasMaxLength(100).IsRequired(); Property(t => t.Name).HasMaxLength(100).IsRequired(); } } public class TestContext : DbContext { public DbSet<Post> Posts { get; set; } public DbSet<Author> Authors { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new PostConfiguration()); modelBuilder.Configurations.Add(new AuthorConfiguration()); base.OnModelCreating(modelBuilder); } } public class Initializer : DropCreateDatabaseAlways<TestContext> { protected override void Seed(TestContext context) { var post = new Post() { Title = "Post1", Content = "Content1", PostedDate = DateTime.Now }; var author = new Author() { Name = "张三", Email = "zhangsan@126.com", Bio = "张三的简历" }; var author1 = new Author() { Name = "李四", Email = "lisi@126.com", Bio = "李四的简历" }; var author2 = new Author() { Name = "王五", Email = "wangwu@126.com", Bio = "王五的简历" }; post.Authors.Add(author); post.Authors.Add(author1); context.Posts.Add(post); post = new Post() { Title = "Post2", Content = "Content2", PostedDate = DateTime.Now }; post.Authors.Add(author); post.Authors.Add(author2); context.Posts.Add(post); context.SaveChanges(); } }
相关推荐
**MVC3 Entity Framework CRUD详解** 在Web开发领域,ASP.NET MVC框架以其清晰的模型-视图-控制器(MVC)架构模式而受到广泛的欢迎。MVC3是该框架的一个版本,提供了更好的性能和更多的特性。同时,Entity ...
#### 标题理解:“ADO.NET Entityframework 書籍” 本书籍主要介绍了ADO.NET与Entity Framework的核心概念、技术细节及其在现代软件开发中的应用。其中特别强调了DbContext作为Entity Framework的一个关键组件,在...
**Entity Framework详解** - **EDM (Entity Data Model)**:是EF的核心,它定义了应用程序和数据库之间的数据模型。EDM分为三个主要部分: - **CSDL (Conceptual Schema Definition Language)**:描述应用程序的...
LINQ to Entities是LINQ技术在Entity Framework中的具体实现,它提供了一种使用LINQ查询Entity Framework实体数据模型的方法。LINQ to Entities可以生成eSQL(Entity SQL),并支持使用LINQ语法对实体框架服务层进行...
**Entity Framework详解** Entity Framework通过创建模型类和数据库之间的映射,简化了数据库操作。开发者可以操作对象而不是直接执行SQL,从而降低了数据库相关的复杂性。它支持Code First、Model First和Database...
2. `Install-Package Microsoft.EntityFrameworkCore.Tools –Pre` - 安装预览版本的Entity Framework Core工具,用于数据库上下文生成。 3. `Install-Package Microsoft.EntityFrameworkCore.SqlServer.Design` - ...
【EntityFrameworkCore详解】 EntityFrameworkCore(简称EF Core)是微软开发的一个轻量级、高性能的ORM框架,它是Entity Framework的最新版本。ORM(对象关系映射)允许开发者使用面向对象的方式来操作数据库,...
《Entity Framework 4 in Action》是一本详尽而实用的指南,它不仅深入浅出地讲解了实体框架的基本概念和技术细节,还提供了丰富的实例帮助读者掌握实际应用技巧。对于希望在.NET平台上开发高性能数据驱动应用的...
Entity Framework是微软提供的一种用于.NET应用程序的数据访问技术,它支持多种数据库平台,并且具有ORM(对象关系映射)功能,能够简化数据访问层的开发工作。 **描述:“Julia Lerman与Rowan Miller的关于Code ...
从最初的ADO.NET,到后来出现的各种简化封装和技术革新,如SqlHelper、DAAB(Data Access Application Block)、LINQ,直至现在广泛推荐使用的Entity Framework,这一路见证了.NET平台上数据访问技术的发展历程。...
《MySQL Entity Framework实战示例详解》 MySQL Entity Framework(简称EF)是.NET框架下的一款ORM(对象关系映射)工具,它允许开发人员使用面向对象的编程方式来操作数据库,而无需关注底层的SQL语句。本篇将通过...
### 实体框架编程(Entity Framework)详解 #### 一、实体框架编程简介 实体框架(Entity Framework,简称EF)是一种由微软开发的数据访问技术,它为.NET开发人员提供了一种新的方式来处理关系型数据库中的数据。...
这些实例可能涉及GUI编程(如Windows Forms或WPF)、数据库交互(ADO.NET或Entity Framework)、网络编程、XML处理、文件I/O操作等。通过解决这些实际问题,读者可以提升编程技能,积累实战经验。 高级主题方面,C#...
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 其他配置 --> <property name="basePackage" value="com.example.mapper" /> <!-- ...
Entity Framework是微软提供的一种对象关系映射(ORM)框架,它允许开发者使用面向对象的编程方式来操作数据库。在MVP模式中,Entity Framework可以作为数据访问层,简化数据库交互。开发者可以创建实体类来表示...