asp.net mvc框架之使用EF一對多關系的設計及使用


在開發過程中,學生和教室的關系(一個學生只能對應一個教室,一個教室對應多個學生),部門的領導和部門的職員等,幾乎無處不在。

以學生和教室的關系:在學校中,一個學生必須對應一個班級,如果一個好學生的話,他不僅對應一個班級,而且學校還會再開一個學霸班在休息日或者放學后進行上課。所以分析:學生必須對應一個班級(一對多關系),但是一個學生可能會對應一個學霸班(有的學生在學霸班,有的學生不能上學霸班)。

1.創建數據庫中的表:

Class3表

Id  --編號(int)

Name  --班級名稱(nvarchar(50))

 

Student3表

Id --編號(int)

Name --學生名稱(nvarchar(50))

ClassId --班級編號(int,外鍵關聯Class3的Id)

SYClassId  --特殊班級編號(int,外鍵關聯Class3的Id)

 

2.安裝EntityFramework框架 --   Install-Package EntityFramework

 

3.創建實體類(Student3,Class3)

public class Class3
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
public class Student3
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int ClassId { get; set; }
        //int?表示對應字段的表中的列可以為空
        public int? SYClassId { get; set; }
        //對應外鍵,要聲明一個關於外鍵關聯的主鍵表的類型,並且命名方式:外鍵:名Id(或名_Id);對應的外鍵的主鍵表類型是外鍵名減去Id
        public virtual Class3 Class { get; set; }
        public virtual Class3 SYClass { get; set; }
    }

 

4.創建Student3和Class3的配置類

public class Class3Config:EntityTypeConfiguration<Class3>
    {
        public Class3Config()
        {
            this.ToTable("T_Classes3");
        }
    }
public class Students3Config:EntityTypeConfiguration<Student3>
    {
        public Students3Config()
        {
            this.ToTable("T_Students3");
            this.HasRequired(s => s.Class).WithMany().HasForeignKey(c => c.ClassId);
            this.HasOptional(s => s.SYClass).WithMany().HasForeignKey(c => c.SYClassId);
        }
    }

其中定義的規則就是:Has...(s=>s.外鍵的主鍵表類型).with...().ForeignKey(外鍵);  

判斷規則:從左向右,例如:學生必須對應一個班級,一個班級一定對應多個學生,所以就是選擇HasRequired->WithMany;學生可能對應一個特殊班級,一個特殊班級一定對應多個學生,所以選擇:HasOptional->WithMany

 

5.創建繼承DbContext的子類Test3DbContext,添加無參數的構造函數,重寫OnModelCreating方法

public class Test3DbContext:DbContext
    {
        public Test3DbContext():base("name=conn1")
        {

        }

        public DbSet<Class3> Classes3 { get; set; }
        public DbSet<Student3> Students3 { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly());
        }
    }

幾點重要的注意點:

(1)base()里面要寫數據庫字符串連接名稱

(2)有多個個實體類,創建多少個DbSet<T>類型的屬性

 

6.實現一對多關系,添加到數據庫中

Test3DbContext tdc3 = new Test3DbContext();

            Class3 cls1 = new Class3();
            cls1.Name = "初一1班";
            tdc3.Classes3.Add(cls1);

            Class3 cls2 = new Class3();
            cls2.Name = "初一2班";
            tdc3.Classes3.Add(cls2);

            Class3 cls3 = new Class3();
            cls3.Name = "學霸先進班";
            tdc3.Classes3.Add(cls3);

            Student3 s1 = new Student3();
            s1.Name = "張三";
            s1.Class = cls1;
            tdc3.Students3.Add(s1);

            Student3 s2 = new Student3();
            s2.Name = "李四";
            s2.Class = cls2;
            s2.SYClass = cls3;
            tdc3.Students3.Add(s2);

            tdc3.SaveChanges();


            Console.WriteLine("ok");
            Console.ReadKey();

 

注意點:

1.在Student3實體類中添加Class3數據類型的屬性,屬性名不一定非要叫這個,只是習慣外鍵去掉Id,但是必須要添加virtual

2.對於可空字段:引用類型是默認可空的,值類型字段需要long? 、int?

3.對於一對多關系,可以在Class3中配置public virtual ICollection<Student3> Students{get;set;} = new List<Students>();屬性。最好給這個屬性初始化一個對象,而這樣初始化一個對象只能在C#6.0中使用,如果6.0以下的話需要在構造函數中進行初始化。建議不要這樣使用,因為會造成耦合度高。

使用:

Test3DbContext tdc3 = new Test3DbContext();

Class3 c1 = new Class3{Name="高一1班"};

tdc3.Classes3.Add(c1);

Student3 s1 = new Student3{Name="張三"};

Student3 s2 = new Student3{Name="李四"};

 

c1.Students.Add(s1);//相當於將s1對象的學生加入到了c1對象的班級中

4.一對多的配置:(在每個實體類的配置類中進行配置)

(1)關系映射基本套路:this.Has***(p=>p.AAA).With***().HasForeignKey(s=>s.AAAId);  當前表和AAA屬性的表的關系是:當前表->AAA對應的數據類型的表的對應關系,With***AAA對應當前表的關系。

HasOptional() 有一個可選的(可以為空)

HasRequired() 必須有一個(不能為空)

HasMany() 有很多

同理:

WithOption()

WithRequired()

WithMany()

5.Fluent API的配置

(1)HasMaxLength設定字段的最大長度

this.Property(p=>p.Name).HasMaxLength(50)設置Name屬性長度為50

當如果使用Name字段插入一個超出50長度的字符串,會報DbEntityValidationException異常,這個異常的Message中看不到詳細的錯誤消息,要看EntityValidationException屬性的值,具體如下:

。。。

。。。

try

{

tdc3.SaveChanges();

}

catch(DbEntityValidationException ex)

{

  StringBuilder sb = new StringBuilder();

  foreach(var ve in ex.EntityValidationErrors.SelectMany(eve=>eve.ValidationErrors))

  {

    sb.AppendLine(ve.PropertyName+":"+ve.ErrorMessage);

  }

  Console.WriteLine(sb);

}

(2)字段是否可空(針對於引用類型)

this.Property(p=>p.Name).IsRequired()屬性不能為空

this.Property(p=>p.Name).IsOptional() 屬性可以為空(雞肋,原因是引用類型默認為空)

(3)主鍵如果不是默認的Id,那么就需要配置

主鍵:this.HasKey(p=>p.pId);

(4)this.Property(p=>p.Name).IsUnicode(false);對應的數據類型是varchar類型。IsUnicode(false)表示varchar類型,IsUnicode(true)表示nvarchar類型

(5)this.Property(p.p.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity) 指定字段是自動增長類型

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM