【配置关系】—Entity Framework实例详解

转:http://www.58os.com/Article/HTML/CNTopic-561.html

实体间的关系,简单来说无非就是一对一、一对多、多对多,根据方向性来说又分为双向和单向。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

下面是用到的类:

   1:      public class Person
   2:      {
   3:          public int PersonId { get; set; }
   4:          public int SocialSecurityNumber { get; set; }
   5:          public string FirstName { get; set; }
   6:          public string LastName { get; set; }
   7:          public byte[] RowVersion { get; set; }
   8:          public PersonPhoto Photo { get; set; }
   9:      }
  10:   
  11:      public class PersonPhoto
  12:      {
  13:          public int PersonId { get; set; }
  14:          public byte[] Photo { get; set; }
  15:          public string Caption { get; set; }
  16:          public Person PhotoOf { get; set; }
  17:      }

因为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:

   1: public class Person

   2: {

   3:     public int PersonId { get; set; }

   4:     public int SocialSecurityNumber { get; set; }

   5:     public string FirstName { get; set; }

   6:     public string LastName { get; set; }

   7:     public byte[] RowVersion { get; set; }

   8:     public PersonPhoto Photo { get; set; }

   9: }

  10:  

  11: public class PersonPhoto

  12: {

  13:     public int PersonId { get; set; }

  14:     public byte[] Photo { get; set; }

  15:     public string Caption { get; set; }

  16:     public Person PhotoOf { get; set; }

  17: }

  18:  

  19: //配置Person

  20: public class PersonConfiguration : EntityTypeConfiguration<Person>

  21: {

  22:     public PersonConfiguration()

  23:     {

  24:         //主键

  25:         HasKey(t => t.PersonId);

  26:         //并发检查

  27:         Property(t => t.SocialSecurityNumber).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).IsConcurrencyToken();

  28:         //长度50 不为空

  29:         Property(t => t.FirstName).IsRequired().HasMaxLength(50);

  30:         //长度50 不为空

  31:         Property(t => t.LastName).IsRequired().HasMaxLength(50);

  32:         //并发检查

  33:         Property(t => t.RowVersion).IsRowVersion();

  34:         //HasRequired(t => t.Photo).WithRequiredPrincipal(t => t.PhotoOf);

  35:         //HasOptional(t => t.Photo).WithRequired(t => t.PhotoOf);

  36:     }

  37: }

  38:  

  39: //配置PersonPhoto

  40: public class PersonPhotoConfiguration : EntityTypeConfiguration<PersonPhoto>

  41: {

  42:     public PersonPhotoConfiguration()

  43:     {

  44:         //主键

  45:         HasKey(t => t.PersonId);

  46:         //长度50

  47:         Property(t => t.Caption).HasMaxLength(50);

  48:         //必须从属于Person

  49:         HasRequired(t => t.PhotoOf).WithRequiredDependent(t => t.Photo);

  50:     }

  51: }

  52:  

  53: public class BreakAwayContext : DbContext

  54: {

  55:     public DbSet<Person> People { get; set; }

  56:     public DbSet<PersonPhoto> Photos { get; set; }

  57:  

  58:     protected override void OnModelCreating(DbModelBuilder modelBuilder)

  59:     {

  60:         modelBuilder.Configurations.Add(new PersonConfiguration());

  61:         modelBuilder.Configurations.Add(new PersonPhotoConfiguration());

  62:         base.OnModelCreating(modelBuilder);

  63:     }

  64: }

  65:  

  66: public class Initializer : DropCreateDatabaseAlways<BreakAwayContext>

  67: {

  68:     public Initializer()

  69:     {

  70:     }

  71:  

  72:     //创建数据库时 Seed数据

  73:     protected override void Seed(BreakAwayContext context)

  74:     {

  75:         context.People.Add(new Person()

  76:         {

  77:             FirstName = "E",

  78:             LastName = "F",

  79:             SocialSecurityNumber = 123456,

  80:             Photo = new PersonPhoto()

  81:             {

  82:                 Caption = "这是照片",

  83:                 Photo = new byte[] { }

  84:             }

  85:         });

  86:         context.SaveChanges();

  87:     }

  88: }

测试程序

   1: [TestClass]

   2: public class UnitTest1

   3: {

   4:     [TestMethod]

   5:     public void ShouldReturnAPersonWithPhoto()

   6:     {

   7:         //Arrange

   8:         var init = new Initializer();

   9:         Person person;

  10:         using (var context = new BreakAwayContext())

  11:         {

  12:             init.InitializeDatabase(context);

  13:             //Act

  14:             person = context.People.Include(t => t.Photo).FirstOrDefault();

  15:         }

  16:         //Assert

  17:         Assert.IsNotNull(person);

  18:         Assert.IsNotNull(person.Photo);

  19:     }

  20: }

测试结果:

QQ截图20121110174644

二、一对多

下面是用到的类:

   1:      public class Blog
   2:      {
   3:          public Blog()
   4:          {
   5:              Posts = new List<Post>();
   6:          }
   7:   
   8:          public int Id { get; set; }
   9:          public DateTime Creationdate { get; set; }
  10:          public string ShortDescription { get; set; }
  11:          public string Title { get; set; }
  12:          public List<Post> Posts { get; set; }
  13:      }
  14:   
  15:      public class Post
  16:      {
  17:          public int Id { get; set; }
  18:          public string Title { get; set; }
  19:          public string Content { get; set; }
  20:          public DateTime PostedDate { get; set; }
  21:   
  22:          public Nullable<int> BlogId { get; set; }
  23:          public virtual Blog Blog { get; set; }
  24:   
  25:          public int PrimaryAuthorId { get; set; }
  26:          public virtual Author PrimaryAuthor { get; set; }
  27:          public Nullable<int> SecondaryAuthorId { get; set; }
  28:          public virtual Author SecondaryAuthor { get; set; }
  29:      }
  30:   
  31:      public class Author
  32:      {
  33:          public int Id { get; set; }
  34:          public string Name { get; set; }
  35:          public string Email { get; set; }
  36:          //个人简历
  37:          public string Bio { get; set; }
  38:   
  39:          public List<Post> PrimaryAuthorFor { get; set; }
  40:          public List<Post> SecondaryAuthorFor { get; set; }
  41:      }

配置一对多关系常用的方法有:

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:

   1: public class Blog

   2: {

   3:     public Blog()

   4:     {

   5:         Posts = new List<Post>();

   6:     }

   7:  

   8:     public int Id { get; set; }

   9:     public DateTime Creationdate { get; set; }

  10:     public string ShortDescription { get; set; }

  11:     public string Title { get; set; }

  12:     public List<Post> Posts { get; set; }

  13: }

  14:  

  15: public class Post

  16: {

  17:     public int Id { get; set; }

  18:     public string Title { get; set; }

  19:     public string Content { get; set; }

  20:     public DateTime PostedDate { get; set; }

  21:  

  22:     //Post可以不归属到Blog独立存在,注意这里的外键属性要设置为可空的

  23:     public Nullable<int> BlogId { get; set; }

  24:     public virtual Blog Blog { get; set; }

  25:  

  26:     public int PrimaryAuthorId { get; set; }

  27:     public virtual Author PrimaryAuthor { get; set; }

  28:     public Nullable<int> SecondaryAuthorId { get; set; }

  29:     public virtual Author SecondaryAuthor { get; set; }

  30: }

  31:  

  32: public class Author

  33: {

  34:     public int Id { get; set; }

  35:     public string Name { get; set; }

  36:     public string Email { get; set; }

  37:     //个人简历

  38:     public string Bio { get; set; }

  39:  

  40:     public List<Post> PrimaryAuthorFor { get; set; }

  41:     public List<Post> SecondaryAuthorFor { get; set; }

  42: }

  43:  

  44: public class BlogConfiguratioin : EntityTypeConfiguration<Blog>

  45: {

  46:     public BlogConfiguratioin()

  47:     {

  48:         ToTable("Blogs");

  49:         HasKey(t => t.Id);

  50:         Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  51:         Property(t => t.Title).IsRequired().HasMaxLength(250);

  52:         Property(t => t.Creationdate).HasColumnName("CreationDate").IsRequired();

  53:         Property(t => t.ShortDescription).HasColumnType("Text").IsMaxLength().IsOptional().HasColumnName("Description");

  54:         //配置Blog和Post的一对多关系,Blog对Post是可选的,外键BlogId,并设置为级联删除

  55:         HasMany(t => t.Posts).WithOptional(t => t.Blog).HasForeignKey(t => t.BlogId).WillCascadeOnDelete();

  56:     }

  57: }

  58:  

  59: public class PostConfiguration : EntityTypeConfiguration<Post>

  60: {

  61:     public PostConfiguration()

  62:     {

  63:         ToTable("Posts");

  64:         HasKey(t => t.Id);

  65:         Property(t => t.Id).HasColumnName("PostId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  66:         Property(t => t.Content).HasColumnName("Body").IsMaxLength();

  67:         Property(t => t.PostedDate).HasColumnName("PostedDate");

  68:         Property(t => t.Title).HasColumnName("Title").IsMaxLength();

  69:         //配置反转属性,集合属性PrimaryAuthorFor匹配PrimaryAuthor

  70:         HasRequired(t => t.PrimaryAuthor).WithMany(t => t.PrimaryAuthorFor);

  71:         //配置反转属性,集合属性SecondaryAuthorFor匹配SecondaryAuthor

  72:         HasOptional(t => t.SecondaryAuthor).WithMany(t => t.SecondaryAuthorFor);

  73:     }

  74: }

  75:  

  76: public class AuthorConfiguration : EntityTypeConfiguration<Author>

  77: {

  78:     public AuthorConfiguration()

  79:     {

  80:         ToTable("Authors");

  81:         HasKey(t => t.Id).Property(t => t.Id).HasColumnName("AuthorId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  82:         Property(t => t.Name).IsRequired().HasMaxLength(50);

  83:         Property(t => t.Email).IsRequired().HasMaxLength(50);

  84:         Property(t => t.Bio).HasMaxLength(1000);

  85:     }

  86: }

  87:  

  88: public class BreakAwayContext : DbContext

  89: {

  90:     public DbSet<Blog> Blogs { get; set; }

  91:     public DbSet<Post> Posts { get; set; }

  92:     public DbSet<Author> Authors { get; set; }

  93:  

  94:     protected override void OnModelCreating(DbModelBuilder modelBuilder)

  95:     {

  96:         modelBuilder.Configurations.Add(new BlogConfiguratioin());

  97:         modelBuilder.Configurations.Add(new PostConfiguration());

  98:         modelBuilder.Configurations.Add(new AuthorConfiguration());

  99:         base.OnModelCreating(modelBuilder);

 100:     }

 101: }

 102:  

 103: public class Initializer : DropCreateDatabaseAlways<BreakAwayContext>

 104: {

 105:     public Initializer()

 106:     {

 107:     }

 108:  

 109:     protected override void Seed(BreakAwayContext context)

 110:     {

 111:         var primaryAuthor = new Author()

 112:         {

 113:             Name = "张三",

 114:             Email = "zhangsan@126.com",

 115:             Bio = "张三的简历"

 116:         };

 117:         var secondaryAuthor = new Author()

 118:         {

 119:             Name = "李四",

 120:             Email = "lisi@126.com",

 121:             Bio = "李四的简历"

 122:         };

 123:         var blog = new Blog()

 124:         {

 125:             Title = "EF",

 126:             ShortDescription = "关于EF的博客",

 127:             Creationdate = DateTime.Now

 128:         };

 129:         blog.Posts.Add(new Post()

 130:         {

 131:             Title = "配置关系",

 132:             PostedDate = DateTime.Now,

 133:             Content = "这是Post的内容",

 134:             PrimaryAuthor = primaryAuthor,

 135:             SecondaryAuthor = secondaryAuthor

 136:         });

 137:         context.Blogs.Add(blog);

 138:         context.SaveChanges();

 139:     }

 140: }

测试程序:

   1: [TestClass]

   2: public class OneToManyTest

   3: {

   4:     [TestMethod]

   5:     public void ShouldReturnBlogWithPosts()

   6:     {

   7:         //Arrage

   8:         Database.SetInitializer(new Initializer());

   9:         var context = new BreakAwayContext();

  10:         //Act

  11:         var blog = context.Blogs.Include(t => t.Posts).FirstOrDefault();

  12:         //Assert

  13:         Assert.IsNotNull(blog);

  14:         Assert.IsNotNull(blog.Posts);

  15:         Assert.IsNotNull(blog.Posts.FirstOrDefault().PrimaryAuthor);

  16:     }

  17: }

测试结果:

QQ截图20121110235536

三、多对多

下面是配置多对多关系用到的类,跟一对多差不多,只不过Post和Author的关系变成多对多的了。

   1:      public class Post
   2:      {
   3:          public int Id { get; set; }
   4:          public string Title { get; set; }
   5:          public string Content { get; set; }
   6:          public DateTime PostedDate { get; set; }
   7:   
   8:          public virtual List<Author> Authors { get; set; }
   9:      }
  10:   
  11:      public class Author
  12:      {
  13:          public int Id { get; set; }
  14:          public string Name { get; set; }
  15:          public string Email { get; set; }
  16:          //个人简历
  17:          public string Bio { get; set; }
  18:   
  19:          public virtual List<Post> Posts { get; set; }
  20:      }

一篇文章有多个作者,一个作者著有多篇文章。

配置多对多关系使用HasMany和WithMany方法,可以使用Map配置生成关联表的名字。

下面是配置多对多关系的Demo:

   1: public class Post

   2: {

   3:     public Post()

   4:     {

   5:         Authors = new List<Author>();

   6:     }

   7:  

   8:     public int Id { get; set; }

   9:     public string Title { get; set; }

  10:     public string Content { get; set; }

  11:     public DateTime PostedDate { get; set; }

  12:  

  13:     public virtual List<Author> Authors { get; set; }

  14: }

  15:  

  16: public class Author

  17: {

  18:     public Author()

  19:     {

  20:         Posts = new List<Post>();

  21:     }

  22:  

  23:     public int Id { get; set; }

  24:     public string Name { get; set; }

  25:     public string Email { get; set; }

  26:     //个人简历

  27:     public string Bio { get; set; }

  28:  

  29:     public virtual List<Post> Posts { get; set; }

  30: }

  31:  

  32: public class PostConfiguration : EntityTypeConfiguration<Post>

  33: {

  34:     public PostConfiguration()

  35:     {

  36:         ToTable("Posts");

  37:         HasKey(t => t.Id);

  38:         Property(t => t.Id).HasColumnName("PostId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  39:         Property(t => t.Content).HasColumnName("Body").IsMaxLength();

  40:         Property(t => t.PostedDate).HasColumnName("PostedDate");

  41:         Property(t => t.Title).HasColumnName("Title").IsMaxLength();

  42:         //配置多对多关系 ToTable 配置生成的关联表名字 MapLeftKey默认表示调用HasMany的实体的主键

  43:         //本例中如果不使用MapLeftKey默认生成Post_Id

  44:         HasMany(t => t.Authors).WithMany(t => t.Posts).Map(m =>

  45:             {

  46:                 m.ToTable("PostAuthor");

  47:                 m.MapLeftKey("PostId");

  48:                 m.MapRightKey("AuthorId");

  49:             });

  50:     }

  51: }

  52:  

  53: public class AuthorConfiguration : EntityTypeConfiguration<Author>

  54: {

  55:     public AuthorConfiguration()

  56:     {

  57:         ToTable("Authors");

  58:         HasKey(t => t.Id);

  59:         Property(t => t.Id).HasColumnName("AuthorId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  60:         Property(t => t.Bio).HasColumnType("Text").IsMaxLength();

  61:         Property(t => t.Email).HasMaxLength(100).IsRequired();

  62:         Property(t => t.Name).HasMaxLength(100).IsRequired();

  63:     }

  64: }

  65:  

  66: public class TestContext : DbContext

  67: {

  68:     public DbSet<Post> Posts { get; set; }

  69:     public DbSet<Author> Authors { get; set; }

  70:  

  71:     protected override void OnModelCreating(DbModelBuilder modelBuilder)

  72:     {

  73:         modelBuilder.Configurations.Add(new PostConfiguration());

  74:         modelBuilder.Configurations.Add(new AuthorConfiguration());

  75:         base.OnModelCreating(modelBuilder);

  76:     }

  77: }

  78:  

  79: public class Initializer : DropCreateDatabaseAlways<TestContext>

  80: {

  81:     protected override void Seed(TestContext context)

  82:     {

  83:         var post = new Post()

  84:         {

  85:             Title = "Post1",

  86:             Content = "Content1",

  87:             PostedDate = DateTime.Now

  88:         };

  89:         var author = new Author()

  90:         {

  91:             Name = "张三",

  92:             Email = "zhangsan@126.com",

  93:             Bio = "张三的简历"

  94:         };

  95:         var author1 = new Author()

  96:         {

  97:             Name = "李四",

  98:             Email = "lisi@126.com",

  99:             Bio = "李四的简历"

 100:         };

 101:         var author2 = new Author()

 102:         {

 103:             Name = "王五",

 104:             Email = "wangwu@126.com",

 105:             Bio = "王五的简历"

 106:         };

 107:         post.Authors.Add(author);

 108:         post.Authors.Add(author1);

 109:         context.Posts.Add(post);

 110:         post = new Post()

 111:         {

 112:             Title = "Post2",

 113:             Content = "Content2",

 114:             PostedDate = DateTime.Now

 115:         };

 116:         post.Authors.Add(author);

 117:         post.Authors.Add(author2);

 118:         context.Posts.Add(post);

 119:         context.SaveChanges();

 120:     }

 121: }

测试程序:

   1: [TestClass]

   2: public class ManyToManyTest

   3: {

   4:     [TestMethod]

   5:     public void ShouldReturnPostWithAuthors()

   6:     {

   7:         //Arrage

   8:         var init = new Initializer();

   9:         var context = new ManyToMany.TestContext();

  10:         init.InitializeDatabase(context);

  11:         //Act

  12:         var post = context.Posts.Include(t => t.Authors).FirstOrDefault();

  13:         //Assert

  14:         Assert.IsNotNull(post);

  15:         Assert.AreEqual(2, post.Authors.Count);

  16:         Assert.AreEqual("李四", post.Authors[1].Name);

  17:     }

  18: }

测试结果:

QQ截图20121112201038

现在关联表中只有两个字段,如下图所示:

QQ截图20121112202337

如果再加个字段,比如DateAdd,这就需要给关联表定义一个实体。

   1:      public class PostAuthor
   2:      {
   3:          public int PostId { get; set; }
   4:          public int AuthorId { get; set; }
   5:   
   6:          public Post Post { get; set; }
   7:          public Author Author { get; set; }
   8:   
   9:          public DateTime DateAdd { get; set; }
  10:      }

另外需要在Post和Author实体中加入一个集合属性:

   1:          public virtual List<PostAuthor> PostAuthors { get; set; }

另外还需要配置PostAuthor实体,具体代码如下面的Demo所示:

   1: public class Post

   2: {

   3:     public Post()

   4:     {

   5:         PostAuthors = new List<PostAuthor>();

   6:     }

   7:  

   8:     public int Id { get; set; }

   9:     public string Title { get; set; }

  10:     public string Content { get; set; }

  11:     public DateTime PostedDate { get; set; }

  12:  

  13:     //public virtual List<Author> Authors { get; set; }

  14:     public virtual List<PostAuthor> PostAuthors { get; set; }

  15: }

  16:  

  17: public class Author

  18: {

  19:     public Author()

  20:     {

  21:         PostAuthors = new List<PostAuthor>();

  22:     }

  23:  

  24:     public int Id { get; set; }

  25:     public string Name { get; set; }

  26:     public string Email { get; set; }

  27:     //个人简历

  28:     public string Bio { get; set; }

  29:  

  30:     //public virtual List<Post> Posts { get; set; }

  31:     public virtual List<PostAuthor> PostAuthors { get; set; }

  32: }

  33:  

  34: //关联表的实体

  35: public class PostAuthor

  36: {

  37:     public int PostId { get; set; }

  38:     public int AuthorId { get; set; }

  39:  

  40:     public Post Post { get; set; }

  41:     public Author Author { get; set; }

  42:  

  43:     public DateTime? DateAdd { get; set; }

  44: }

  45:  

  46: public class PostConfiguration : EntityTypeConfiguration<Post>

  47: {

  48:     public PostConfiguration()

  49:     {

  50:         ToTable("Posts");

  51:         HasKey(t => t.Id);

  52:         Property(t => t.Id).HasColumnName("PostId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  53:         Property(t => t.Content).HasColumnName("Body").IsMaxLength();

  54:         Property(t => t.PostedDate).HasColumnName("PostedDate");

  55:         Property(t => t.Title).HasColumnName("Title").IsMaxLength();

  56:     }

  57: }

  58:  

  59: public class AuthorConfiguration : EntityTypeConfiguration<Author>

  60: {

  61:     public AuthorConfiguration()

  62:     {

  63:         ToTable("Authors");

  64:         HasKey(t => t.Id);

  65:         Property(t => t.Id).HasColumnName("AuthorId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  66:         Property(t => t.Bio).HasColumnType("Text").IsMaxLength();

  67:         Property(t => t.Email).HasMaxLength(100).IsRequired();

  68:         Property(t => t.Name).HasMaxLength(100).IsRequired();

  69:     }

  70: }

  71:  

  72: //配置关联表实体

  73: public class PostAuthorConfiguration : EntityTypeConfiguration<PostAuthor>

  74: {

  75:     public PostAuthorConfiguration()

  76:     {

  77:         ToTable("PostAuthors");

  78:         //配置组合主键

  79:         HasKey(t => new { t.PostId, t.AuthorId });

  80:         Property(t => t.PostId).HasColumnOrder(0);

  81:         Property(t => t.AuthorId).HasColumnOrder(1);

  82:         //这里是配置一对多关系

  83:         HasRequired(t => t.Post).WithMany(t => t.PostAuthors).HasForeignKey(t => t.PostId);

  84:         HasRequired(t => t.Author).WithMany(t => t.PostAuthors).HasForeignKey(t => t.AuthorId);

  85:     }

  86: }

  87:  

  88: public class TestContext : DbContext

  89: {

  90:     public DbSet<Post> Posts { get; set; }

  91:     public DbSet<Author> Authors { get; set; }

  92:     public DbSet<PostAuthor> PostAuthors { get; set; }

  93:  

  94:     protected override void OnModelCreating(DbModelBuilder modelBuilder)

  95:     {

  96:         modelBuilder.Configurations.Add(new PostConfiguration());

  97:         modelBuilder.Configurations.Add(new AuthorConfiguration());

  98:         modelBuilder.Configurations.Add(new PostAuthorConfiguration());

  99:         base.OnModelCreating(modelBuilder);

 100:     }

 101: }

 102:  

 103: public class Initializer : DropCreateDatabaseAlways<TestContext>

 104: {

 105:     protected override void Seed(TestContext context)

 106:     {

 107:         var post = new Post()

 108:         {

 109:             Title = "Post1",

 110:             Content = "Content1",

 111:             PostedDate = DateTime.Now

 112:         };

 113:         post = context.Posts.Add(post);

 114:         var author = new Author()

 115:         {

 116:             Name = "张三",

 117:             Email = "zhangsan@126.com",

 118:             Bio = "张三的简历"

 119:         };

 120:         var author1 = new Author()

 121:         {

 122:             Name = "李四",

 123:             Email = "lisi@126.com",

 124:             Bio = "李四的简历"

 125:         };

 126:         author = context.Authors.Add(author);

 127:         author1 = context.Authors.Add(author1);

 128:         context.SaveChanges();

 129:         PostAuthor pa1 = new PostAuthor()

 130:         {

 131:             PostId = post.Id,

 132:             AuthorId = author.Id,

 133:             DateAdd = DateTime.Now

 134:         };

 135:         PostAuthor pa2 = new PostAuthor()

 136:         {

 137:             PostId = post.Id,

 138:             AuthorId = author1.Id,

 139:             DateAdd = DateTime.Now

 140:         };

 141:         context.PostAuthors.Add(pa1);

 142:         context.PostAuthors.Add(pa2);

 143:         context.SaveChanges();

 144:     }

 145: }

测试程序:

   1: [TestMethod]

   2: public void ShouldReturnAuthorsWithDateAdd()

   3: {

   4:     //Arrage

   5:     var init = new Initializer();

   6:     var context = new ManyToMany.TestContext();

   7:     init.InitializeDatabase(context);

   8:     //Act

   9:     var post = context.Posts.Include(t => t.PostAuthors).FirstOrDefault();

  10:     //Assert

  11:     Assert.IsNotNull(post);

  12:     Assert.AreEqual(2, post.PostAuthors.Count);

  13:     Assert.IsNotNull(post.PostAuthors[0].DateAdd);

  14: }

测试结果:

QQ截图20121112211304

生成的关联表如下图所示:

QQ截图20121112211859

四、结束语

点击查看《Entity Framework实例详解》系列的其他文章。

如果遇到问题,可以加群:276721846  进行讨论。

另外欢迎大家访问Entity Framework社区,网址是www.ef-community.comwww.ef-community.cn

var isLogined = false; var cb_blogId = 90375; var cb_entryId = 2767089; var cb_blogApp = currentBlogApp; var cb_blogUserGuid = "90331348-10a5-de11-ba8f-001cf0cd104b"; var cb_entryCreatedDate = '2012/11/12 21:53:00'; var enableGoogleAd = true; var googletag = googletag || {}; googletag.cmd = googletag.cmd || [];

原文地址:http://www.cnblogs.com/nianming/archive/2012/11/12/2767089.html
原文地址:https://www.cnblogs.com/jackljf/p/3589273.html