【配置关系】—Entity Framework实例详解
2012-11-12 21:53
281 查看
实体间的关系,简单来说无非就是一对一、一对多、多对多,根据方向性来说又分为双向和单向。CodeFirst在实体关系上有以下约定:
1.两个实体,如果一个实体包含一个引用属性,另一个实体包含一个集合属性,CodeFirst默认约定它们为一对多关系。
2.两个实体,如果只有一个实体包含一个导航属性或一个集合属性,CodeFirst也默认约定它们是一对多关系。
3.两个实体分别包含一个集合属性,CodeFirst默认约定它们为多对多关系。
4.两个实体分别包含一个引用属性,CodeFirst默认约定它们为一对一关系。
5.在一对一关系情况下,需要提供给CodeFirst额外的信息,以确定它们的主从关系。
6.在实体中定义一个外键属性,CodeFirst使用属性是否为空来确定关系是必须还是可选。
配置一对一关系常用的方法:
HasRequired,HasOptional,WithOptional,WithRequiredPrincipal,WithRequiredDependent
下面是用到的类:
[code]{
[/code]
因为Photo是具体人的,所以PersonPhoto使用PersonId作为主键。
下面是一对一关系配置的几种情况:
1.PersonPhoto必须属于一个Person,但是Person不一定有PersonPhoto,这种关系是1:0..1,此种情况下Person是一定存在的,所以它是主从关系主的一方。
或
2.PersonPhoto必须属于一个Person,Person也必须有PersonPhoto,这种关系式1:1,此种情况下,两个都一定存在,要确定主从关系,需要使用WithRequiredPrincipal或WithRequiredDependent。
或
上述两种情况都是真实存在的,不真实存在的就不说了。
下面配置一对一关系贴出Demo:
测试程序
测试结果:
[code]{
[/code]
配置一对多关系常用的方法有:
HasOptional,HasRequired,HasMany
Has方法后面往往跟着With方法
WithOptional,WithRequired,WithMany
下面配置一对多的几种情况:
1.Post一定归属于一个Blog,这种关系是1:n。
或
2.Post可以单独存在,不用归属于Blog,这种关系是0..1:n。
或
设置外键
外键的默认约定:
[TargetTypeKeyName],[TargetTypeName]+[TargetTypeKeyName],or[Navigation
PropertyName]+[TargetTypeKeyName]
本例中,匹配的是[TargetTypeName]+[TargetTypeKeyName],目标类型是Blog,目标类型主键是Id,加起来就是BlogId。下面使用FluentAPI显示设置外键:
设置级联删除
反转属性
在Post实体中,有两个属性:PrimaryAuthor和SecondaryAuthor,第一作者和第二作者。在Author中有两个集合属性,CodeFirst默认不能确定哪个集合属性和Post中的导航属性相匹配。使用FluentAPI配置反转属性,如下:
[code]HasOptional(t=>t.SecondaryAuthor).WithMany(t=>t.SecondaryAuthorFor);
[/code]
下面是配置一对多关系的Demo:
测试程序:
测试结果:
[code]{
[/code]
一篇文章有多个作者,一个作者著有多篇文章。
配置多对多关系使用HasMany和WithMany方法,可以使用Map配置生成关联表的名字。
下面是配置多对多关系的Demo:
测试程序:
测试结果:
现在关联表中只有两个字段,如下图所示:
如果再加个字段,比如DateAdd,这就需要给关联表定义一个实体。
[code]{
[/code]
另外需要在Post和Author实体中加入一个集合属性:
另外还需要配置PostAuthor实体,具体代码如下面的Demo所示:
测试程序:
测试结果:
生成的关联表如下图所示:
点击查看《EntityFramework实例详解》系列的其他文章。
如果遇到问题,可以访问EntityFramework社区,网址是www.ef-community.com或www.ef-community.cn。
1.两个实体,如果一个实体包含一个引用属性,另一个实体包含一个集合属性,CodeFirst默认约定它们为一对多关系。
2.两个实体,如果只有一个实体包含一个导航属性或一个集合属性,CodeFirst也默认约定它们是一对多关系。
3.两个实体分别包含一个集合属性,CodeFirst默认约定它们为多对多关系。
4.两个实体分别包含一个引用属性,CodeFirst默认约定它们为一对一关系。
5.在一对一关系情况下,需要提供给CodeFirst额外的信息,以确定它们的主从关系。
6.在实体中定义一个外键属性,CodeFirst使用属性是否为空来确定关系是必须还是可选。
一、一对一
在CodeFirst中,一对一关系总是需要配置,因为两个实体都包含有一个引用属性,无法确定它们的主从关系。配置一对一关系常用的方法:
HasRequired,HasOptional,WithOptional,WithRequiredPrincipal,WithRequiredDependent
下面是用到的类:
publicclassPerson
[code]{
publicintPersonId{get;set;}
publicintSocialSecurityNumber{get;set;}
publicstringFirstName{get;set;}
publicstringLastName{get;set;}
publicbyte[]RowVersion{get;set;}
publicPersonPhotoPhoto{get;set;}
}
publicclassPersonPhoto
{
publicintPersonId{get;set;}
publicbyte[]Photo{get;set;}
publicstringCaption{get;set;}
publicPersonPhotoOf{get;set;}
}
[/code]
因为Photo是具体人的,所以PersonPhoto使用PersonId作为主键。
下面是一对一关系配置的几种情况:
1.PersonPhoto必须属于一个Person,但是Person不一定有PersonPhoto,这种关系是1:0..1,此种情况下Person是一定存在的,所以它是主从关系主的一方。
HasRequired(t=>t.PhotoOf).WithOptional(t=>t.Photo);
或
HasOptional(t=>t.Photo).WithRequired(t=>t.PhotoOf);
2.PersonPhoto必须属于一个Person,Person也必须有PersonPhoto,这种关系式1:1,此种情况下,两个都一定存在,要确定主从关系,需要使用WithRequiredPrincipal或WithRequiredDependent。
HasRequired(t=>t.PhotoOf).WithRequiredDependent(t=>t.Photo);
或
HasRequired(t=>t.Photo).WithRequiredPrincipal(t=>t.PhotoOf);
上述两种情况都是真实存在的,不真实存在的就不说了。
下面配置一对一关系贴出Demo:
publicclassPerson
{
publicintPersonId{get;set;}
publicintSocialSecurityNumber{get;set;}
publicstringFirstName{get;set;}
publicstringLastName{get;set;}
publicbyte[]RowVersion{get;set;}
publicPersonPhotoPhoto{get;set;}
}
publicclassPersonPhoto
{
publicintPersonId{get;set;}
publicbyte[]Photo{get;set;}
publicstringCaption{get;set;}
publicPersonPhotoOf{get;set;}
}
//配置Person
publicclassPersonConfiguration:EntityTypeConfiguration<Person>
{
publicPersonConfiguration()
{
//主键
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
publicclassPersonPhotoConfiguration:EntityTypeConfiguration<PersonPhoto>
{
publicPersonPhotoConfiguration()
{
//主键
HasKey(t=>t.PersonId);
//长度50
Property(t=>t.Caption).HasMaxLength(50);
//必须从属于Person
HasRequired(t=>t.PhotoOf).WithRequiredDependent(t=>t.Photo);
}
}
publicclassBreakAwayContext:DbContext
{
publicDbSet<Person>People{get;set;}
publicDbSet<PersonPhoto>Photos{get;set;}
protectedoverridevoidOnModelCreating(DbModelBuildermodelBuilder)
{
modelBuilder.Configurations.Add(newPersonConfiguration());
modelBuilder.Configurations.Add(newPersonPhotoConfiguration());
base.OnModelCreating(modelBuilder);
}
}
publicclassInitializer:DropCreateDatabaseAlways<BreakAwayContext>
{
publicInitializer()
{
}
//创建数据库时Seed数据
protectedoverridevoidSeed(BreakAwayContextcontext)
{
context.People.Add(newPerson()
{
FirstName="E",
LastName="F",
SocialSecurityNumber=123456,
Photo=newPersonPhoto()
{
Caption="这是照片",
Photo=newbyte[]{}
}
});
context.SaveChanges();
}
}
测试程序
[TestClass]
publicclassUnitTest1
{
[TestMethod]
publicvoidShouldReturnAPersonWithPhoto()
{
//Arrange
varinit=newInitializer();
Personperson;
using(varcontext=newBreakAwayContext())
{
init.InitializeDatabase(context);
//Act
person=context.People.Include(t=>t.Photo).FirstOrDefault();
}
//Assert
Assert.IsNotNull(person);
Assert.IsNotNull(person.Photo);
}
}
测试结果:
二、一对多
下面是用到的类:publicclassBlog
[code]{
publicBlog()
{
Posts=newList<Post>();
}
publicintId{get;set;}
publicDateTimeCreationdate{get;set;}
publicstringShortDescription{get;set;}
publicstringTitle{get;set;}
publicList<Post>Posts{get;set;}
}
publicclassPost
{
publicintId{get;set;}
publicstringTitle{get;set;}
publicstringContent{get;set;}
publicDateTimePostedDate{get;set;}
publicNullable<int>BlogId{get;set;}
publicvirtualBlogBlog{get;set;}
publicintPrimaryAuthorId{get;set;}
publicvirtualAuthorPrimaryAuthor{get;set;}
publicNullable<int>SecondaryAuthorId{get;set;}
publicvirtualAuthorSecondaryAuthor{get;set;}
}
publicclassAuthor
{
publicintId{get;set;}
publicstringName{get;set;}
publicstringEmail{get;set;}
//个人简历
publicstringBio{get;set;}
publicList<Post>PrimaryAuthorFor{get;set;}
publicList<Post>SecondaryAuthorFor{get;set;}
}
[/code]
配置一对多关系常用的方法有:
HasOptional,HasRequired,HasMany
Has方法后面往往跟着With方法
WithOptional,WithRequired,WithMany
下面配置一对多的几种情况:
1.Post一定归属于一个Blog,这种关系是1:n。
HasMany(x=>x.Posts).WithRequired(x=>x.Blog)
或
HasRequired(x=>x.Blog).WithMany(x=>x.Posts)
2.Post可以单独存在,不用归属于Blog,这种关系是0..1:n。
HasMany(x=>x.Posts).WithOptional(x=>x.Blog)
或
HasOptional(x=>x.Blog).WithMany(x=>x.Posts)
设置外键
外键的默认约定:
[TargetTypeKeyName],[TargetTypeName]+[TargetTypeKeyName],or[Navigation
PropertyName]+[TargetTypeKeyName]
本例中,匹配的是[TargetTypeName]+[TargetTypeKeyName],目标类型是Blog,目标类型主键是Id,加起来就是BlogId。下面使用FluentAPI显示设置外键:
HasMany(x=>x.Posts).WithOptional(x=>x.Blog).HasForeignKey(x=>x.BlogId)
设置级联删除
HasMany(x=>x.Posts).WithOptional(x=>x.Blog).HasForeignKey(x=>x.BlogId).WillCascadeOnDelete();
反转属性
在Post实体中,有两个属性:PrimaryAuthor和SecondaryAuthor,第一作者和第二作者。在Author中有两个集合属性,CodeFirst默认不能确定哪个集合属性和Post中的导航属性相匹配。使用FluentAPI配置反转属性,如下:
HasRequired(t=>t.PrimaryAuthor).WithMany(t=>t.PrimaryAuthorFor);
[code]HasOptional(t=>t.SecondaryAuthor).WithMany(t=>t.SecondaryAuthorFor);
[/code]
下面是配置一对多关系的Demo:
publicclassBlog
{
publicBlog()
{
Posts=newList<Post>();
}
publicintId{get;set;}
publicDateTimeCreationdate{get;set;}
publicstringShortDescription{get;set;}
publicstringTitle{get;set;}
publicList<Post>Posts{get;set;}
}
publicclassPost
{
publicintId{get;set;}
publicstringTitle{get;set;}
publicstringContent{get;set;}
publicDateTimePostedDate{get;set;}
//Post可以不归属到Blog独立存在,注意这里的外键属性要设置为可空的
publicNullable<int>BlogId{get;set;}
publicvirtualBlogBlog{get;set;}
publicintPrimaryAuthorId{get;set;}
publicvirtualAuthorPrimaryAuthor{get;set;}
publicNullable<int>SecondaryAuthorId{get;set;}
publicvirtualAuthorSecondaryAuthor{get;set;}
}
publicclassAuthor
{
publicintId{get;set;}
publicstringName{get;set;}
publicstringEmail{get;set;}
//个人简历
publicstringBio{get;set;}
publicList<Post>PrimaryAuthorFor{get;set;}
publicList<Post>SecondaryAuthorFor{get;set;}
}
publicclassBlogConfiguratioin:EntityTypeConfiguration<Blog>
{
publicBlogConfiguratioin()
{
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();
}
}
publicclassPostConfiguration:EntityTypeConfiguration<Post>
{
publicPostConfiguration()
{
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);
}
}
publicclassAuthorConfiguration:EntityTypeConfiguration<Author>
{
publicAuthorConfiguration()
{
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);
}
}
publicclassBreakAwayContext:DbContext
{
publicDbSet<Blog>Blogs{get;set;}
publicDbSet<Post>Posts{get;set;}
publicDbSet<Author>Authors{get;set;}
protectedoverridevoidOnModelCreating(DbModelBuildermodelBuilder)
{
modelBuilder.Configurations.Add(newBlogConfiguratioin());
modelBuilder.Configurations.Add(newPostConfiguration());
modelBuilder.Configurations.Add(newAuthorConfiguration());
base.OnModelCreating(modelBuilder);
}
}
publicclassInitializer:DropCreateDatabaseAlways<BreakAwayContext>
{
publicInitializer()
{
}
protectedoverridevoidSeed(BreakAwayContextcontext)
{
varprimaryAuthor=newAuthor()
{
Name="张三",
Email="zhangsan@126.com",
Bio="张三的简历"
};
varsecondaryAuthor=newAuthor()
{
Name="李四",
Email="lisi@126.com",
Bio="李四的简历"
};
varblog=newBlog()
{
Title="EF",
ShortDescription="关于EF的博客",
Creationdate=DateTime.Now
};
blog.Posts.Add(newPost()
{
Title="配置关系",
PostedDate=DateTime.Now,
Content="这是Post的内容",
PrimaryAuthor=primaryAuthor,
SecondaryAuthor=secondaryAuthor
});
context.Blogs.Add(blog);
context.SaveChanges();
}
}
测试程序:
[TestClass]
publicclassOneToManyTest
{
[TestMethod]
publicvoidShouldReturnBlogWithPosts()
{
//Arrage
Database.SetInitializer(newInitializer());
varcontext=newBreakAwayContext();
//Act
varblog=context.Blogs.Include(t=>t.Posts).FirstOrDefault();
//Assert
Assert.IsNotNull(blog);
Assert.IsNotNull(blog.Posts);
Assert.IsNotNull(blog.Posts.FirstOrDefault().PrimaryAuthor);
}
}
测试结果:
三、多对多
下面是配置多对多关系用到的类,跟一对多差不多,只不过Post和Author的关系变成多对多的了。publicclassPost
[code]{
publicintId{get;set;}
publicstringTitle{get;set;}
publicstringContent{get;set;}
publicDateTimePostedDate{get;set;}
publicvirtualList<Author>Authors{get;set;}
}
publicclassAuthor
{
publicintId{get;set;}
publicstringName{get;set;}
publicstringEmail{get;set;}
//个人简历
publicstringBio{get;set;}
publicvirtualList<Post>Posts{get;set;}
}
[/code]
一篇文章有多个作者,一个作者著有多篇文章。
配置多对多关系使用HasMany和WithMany方法,可以使用Map配置生成关联表的名字。
下面是配置多对多关系的Demo:
publicclassPost
{
publicPost()
{
Authors=newList<Author>();
}
publicintId{get;set;}
publicstringTitle{get;set;}
publicstringContent{get;set;}
publicDateTimePostedDate{get;set;}
publicvirtualList<Author>Authors{get;set;}
}
publicclassAuthor
{
publicAuthor()
{
Posts=newList<Post>();
}
publicintId{get;set;}
publicstringName{get;set;}
publicstringEmail{get;set;}
//个人简历
publicstringBio{get;set;}
publicvirtualList<Post>Posts{get;set;}
}
publicclassPostConfiguration:EntityTypeConfiguration<Post>
{
publicPostConfiguration()
{
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");
});
}
}
publicclassAuthorConfiguration:EntityTypeConfiguration<Author>
{
publicAuthorConfiguration()
{
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();
}
}
publicclassTestContext:DbContext
{
publicDbSet<Post>Posts{get;set;}
publicDbSet<Author>Authors{get;set;}
protectedoverridevoidOnModelCreating(DbModelBuildermodelBuilder)
{
modelBuilder.Configurations.Add(newPostConfiguration());
modelBuilder.Configurations.Add(newAuthorConfiguration());
base.OnModelCreating(modelBuilder);
}
}
publicclassInitializer:DropCreateDatabaseAlways<TestContext>
{
protectedoverridevoidSeed(TestContextcontext)
{
varpost=newPost()
{
Title="Post1",
Content="Content1",
PostedDate=DateTime.Now
};
varauthor=newAuthor()
{
Name="张三",
Email="zhangsan@126.com",
Bio="张三的简历"
};
varauthor1=newAuthor()
{
Name="李四",
Email="lisi@126.com",
Bio="李四的简历"
};
varauthor2=newAuthor()
{
Name="王五",
Email="wangwu@126.com",
Bio="王五的简历"
};
post.Authors.Add(author);
post.Authors.Add(author1);
context.Posts.Add(post);
post=newPost()
{
Title="Post2",
Content="Content2",
PostedDate=DateTime.Now
};
post.Authors.Add(author);
post.Authors.Add(author2);
context.Posts.Add(post);
context.SaveChanges();
}
}
测试程序:
[TestClass]
publicclassManyToManyTest
{
[TestMethod]
publicvoidShouldReturnPostWithAuthors()
{
//Arrage
varinit=newInitializer();
varcontext=newManyToMany.TestContext();
init.InitializeDatabase(context);
//Act
varpost=context.Posts.Include(t=>t.Authors).FirstOrDefault();
//Assert
Assert.IsNotNull(post);
Assert.AreEqual(2,post.Authors.Count);
Assert.AreEqual("李四",post.Authors[1].Name);
}
}
测试结果:
现在关联表中只有两个字段,如下图所示:
如果再加个字段,比如DateAdd,这就需要给关联表定义一个实体。
publicclassPostAuthor
[code]{
publicintPostId{get;set;}
publicintAuthorId{get;set;}
publicPostPost{get;set;}
publicAuthorAuthor{get;set;}
publicDateTimeDateAdd{get;set;}
}
[/code]
另外需要在Post和Author实体中加入一个集合属性:
publicvirtualList<PostAuthor>PostAuthors{get;set;}
另外还需要配置PostAuthor实体,具体代码如下面的Demo所示:
publicclassPost
{
publicPost()
{
PostAuthors=newList<PostAuthor>();
}
publicintId{get;set;}
publicstringTitle{get;set;}
publicstringContent{get;set;}
publicDateTimePostedDate{get;set;}
//publicvirtualList<Author>Authors{get;set;}
publicvirtualList<PostAuthor>PostAuthors{get;set;}
}
publicclassAuthor
{
publicAuthor()
{
PostAuthors=newList<PostAuthor>();
}
publicintId{get;set;}
publicstringName{get;set;}
publicstringEmail{get;set;}
//个人简历
publicstringBio{get;set;}
//publicvirtualList<Post>Posts{get;set;}
publicvirtualList<PostAuthor>PostAuthors{get;set;}
}
//关联表的实体
publicclassPostAuthor
{
publicintPostId{get;set;}
publicintAuthorId{get;set;}
publicPostPost{get;set;}
publicAuthorAuthor{get;set;}
publicDateTime?DateAdd{get;set;}
}
publicclassPostConfiguration:EntityTypeConfiguration<Post>
{
publicPostConfiguration()
{
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();
}
}
publicclassAuthorConfiguration:EntityTypeConfiguration<Author>
{
publicAuthorConfiguration()
{
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();
}
}
//配置关联表实体
publicclassPostAuthorConfiguration:EntityTypeConfiguration<PostAuthor>
{
publicPostAuthorConfiguration()
{
ToTable("PostAuthors");
//配置组合主键
HasKey(t=>new{t.PostId,t.AuthorId});
Property(t=>t.PostId).HasColumnOrder(0);
Property(t=>t.AuthorId).HasColumnOrder(1);
//这里是配置一对多关系
HasRequired(t=>t.Post).WithMany(t=>t.PostAuthors).HasForeignKey(t=>t.PostId);
HasRequired(t=>t.Author).WithMany(t=>t.PostAuthors).HasForeignKey(t=>t.AuthorId);
}
}
publicclassTestContext:DbContext
{
publicDbSet<Post>Posts{get;set;}
publicDbSet<Author>Authors{get;set;}
publicDbSet<PostAuthor>PostAuthors{get;set;}
protectedoverridevoidOnModelCreating(DbModelBuildermodelBuilder)
{
modelBuilder.Configurations.Add(newPostConfiguration());
modelBuilder.Configurations.Add(newAuthorConfiguration());
modelBuilder.Configurations.Add(newPostAuthorConfiguration());
base.OnModelCreating(modelBuilder);
}
}
publicclassInitializer:DropCreateDatabaseAlways<TestContext>
{
protectedoverridevoidSeed(TestContextcontext)
{
varpost=newPost()
{
Title="Post1",
Content="Content1",
PostedDate=DateTime.Now
};
post=context.Posts.Add(post);
varauthor=newAuthor()
{
Name="张三",
Email="zhangsan@126.com",
Bio="张三的简历"
};
varauthor1=newAuthor()
{
Name="李四",
Email="lisi@126.com",
Bio="李四的简历"
};
author=context.Authors.Add(author);
author1=context.Authors.Add(author1);
context.SaveChanges();
PostAuthorpa1=newPostAuthor()
{
PostId=post.Id,
AuthorId=author.Id,
DateAdd=DateTime.Now
};
PostAuthorpa2=newPostAuthor()
{
PostId=post.Id,
AuthorId=author1.Id,
DateAdd=DateTime.Now
};
context.PostAuthors.Add(pa1);
context.PostAuthors.Add(pa2);
context.SaveChanges();
}
}
测试程序:
[TestMethod]
publicvoidShouldReturnAuthorsWithDateAdd()
{
//Arrage
varinit=newInitializer();
varcontext=newManyToMany.TestContext();
init.InitializeDatabase(context);
//Act
varpost=context.Posts.Include(t=>t.PostAuthors).FirstOrDefault();
//Assert
Assert.IsNotNull(post);
Assert.AreEqual(2,post.PostAuthors.Count);
Assert.IsNotNull(post.PostAuthors[0].DateAdd);
}
测试结果:
生成的关联表如下图所示:
四、结束语
如果遇到问题,可以访问
相关文章推荐
- SSH——Hibernate继承关系映射详解(配置+实例+总结)
- 【配置关系】—Entity Framework实例详解
- (转)【配置关系】—Entity Framework实例详解
- 【配置关系】—Entity Framework实例详解
- 【配置关系】—Entity Framework实例详解
- 【配置关系】—Entity Framework实例详解
- 【配置关系】—Entity Framework实例详解-超详细
- Nginx负载均衡配置实例详解
- 【配置属性】—Entity Framework实例详解(DataAnnotations and Fluent API)
- log4j.properties配置详解与实例-全部测试通过
- Syslog配置详解及编程实例
- Nginx负载均衡配置实例详解
- Java简单操作Properties配置文件(实例详解)
- log4j.properties配置详解与实例-全部测试通过
- Linux网络服务之DNS服务器介绍及配置实例详解
- linux 网卡配置详解及实例
- vsftpd.conf 详解与实例配置
- Nginx负载均衡配置实例详解
- 【转】hibernate之关系配置文件详解3
- Nginx负载均衡配置实例详解