Entity Framework使用建模之Code First 多对多

本文介绍如何使用Entity Framework的Code First方法来建模和处理多对多关系,通过示例展示了部门、员工和项目之间的关系。部门与员工之间是一对多关系,而项目与员工之间是多对多关系,详细代码展示如何定义这些实体及其相互关联。

这个示例同时包含了一对多,如下4个类:

部门类    Department

员工类    Employee

项目类    Project

部门和员工是一对多关系

项目和员工是多对多关系

代码如下:

部门类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace EFLabCodeFirst
{
    [Table("Departs")]
    public class Department
    {
        [Key]
        [DatabaseGenerated( System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]
        [Column("DEPART_ID")]
        [MaxLength(6)]
        public string DepartID { get; set; }

        [Column("DEPART_NAME")]
        [MaxLength(16)]
        public string DepartName { get; set; }

        [Column("DEPART_BUILD_TIME")]
        public DateTime? DepartBuildTime { get; set; }

        /// <summary>
        /// 一个部门有多个员工
        /// </summary>
        public virtual ICollection<Employee> Employees{get;set;}

    }
}

项目类:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace EFLabCodeFirst
{
    /// <summary>
    /// 项目,一个项目可以有多个员工参与
    /// </summary>
    [Table("Projects")]
    public class Project
    {
        /// <summary>
        /// 项目编号,按照Code First约定会生成标识列
        /// </summary>
        public int? ProjectId { get; set; }
        /// <summary>
        /// 项目名称
        /// </summary>
        [Required]
        [MaxLength(32)]
        public string ProjectName { get; set; }
        /// <summary>
        /// 项目启动时间
        /// </summary>
        public DateTime? ProjectStartTime { get; set; }

        /// <summary>
        /// 参与此项目的员工的集合
        /// </summary>
        public virtual ICollection<Employee> Employees { get; set; }
    }
}

员工类:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace EFLabCodeFirst
{
    /// <summary>
    /// 员工,一个员工可以参与多个项目
    /// </summary>
    [Table("Employees")]
    public class Employee
    {
        [Key]
        [DatabaseGenerated( System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]
        [MaxLength(8)]
        public string EmployeeID { get; set; }

        [Column("DEPART_ID")]
        [MaxLength(6)]
        public string DepartID { get; set; }

        /// <summary>
        /// 一个员工属于一个部门
        /// </summary>
        [ForeignKey("DepartID")]
        [InverseProperty("Employees")]
        public virtual Department Department {get;set;}

        [Required]
        [MaxLength(8)]
        public string EmployeeName { get; set; }
        public int? EmployeeAge { get; set; }

        /// <summary>
        /// 当前员工参与的项目的集合
        /// </summary>
        public virtual ICollection<Project> Projects { get; set; }
    }
}

CodeFirstDbContext类:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Objects;
using System.ComponentModel.DataAnnotations;

namespace EFLabCodeFirst
{
    /// <summary>
    /// 自定义类必须继承自DbContext,DbContext来自EF4.1的EntiyFramework.dll这个程序集
    /// </summary>
    public class CodeFirstDbContext:DbContext
    {
        public DbSet<GameUser> GameUsers { get; set; }
        public DbSet<GameRole> GameRoles { get; set; }
        public DbSet<Project> Projects { get; set; }
        public DbSet<Employee> Employees { get; set; }

        public CodeFirstDbContext()
        {

        }

        public CodeFirstDbContext(string conn):base(conn)  
        {
            //是否启用延迟加载:
            //  true:   延迟加载(Lazy Loading):获取实体时不会加载其导航属性,一旦用到导航属性就会自动加载
            //  false:  直接加载(Eager loading):通过 Include 之类的方法显示加载导航属性,获取实体时会即时加载通过 Include 指定的导航属性
            this.Configuration.LazyLoadingEnabled = true;   

            this.Configuration.AutoDetectChangesEnabled = true;  //自动监测变化,默认值为 true

        }

        /// <summary>
        /// 实体到数据库结构的映射是通过默认的约定来进行的,如果需要修改的话,有两种方式,分别是:Data Annotations 和 Fluent API
        //  以下示范通过 Fluent API 来修改实体到数据库结构的映射
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<GameRole>()
                    .Property(p => p.GameRoleID)
                    .HasColumnName("GameRoleID")//设置映射的表字段名
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)//设置映射字段的值生成方式为标识列
                    .IsRequired();//设置字段值是必须的


            modelBuilder.Entity<GameRole>()
                    .Property(p => p.GameRoleName)
                    .HasMaxLength(32)//字段长度
                    .IsOptional()//字段的值可以为空
                    .IsUnicode()//字段值类型为nvarchar
                    .IsVariableLength();//字段长度是可变的

            modelBuilder.Entity<Project>()//注册一个实体类型为模型的一部分,返回的对象用于配置这个实体
                    .HasMany<Employee>(p => p.Employees)//从这个实体类型配置一个多关系[此处表明一个项目拥有一个员工对象的集合]
                    .WithMany(e => e.Projects)//配置这个多对多关系的另一端,另一端通过导航属性能够被访问(此处表明一个员工拥有一个项目对象的集合)
                    .Map(m => {               //配置用于存储关系的外键字段和表
                        m.MapLeftKey("ProjectID");//引用的左表字段
                        m.MapRightKey("EmployeeID");//引用的右表字段
                        m.ToTable("ProjectEmployee");//中间表
                    });


            base.OnModelCreating(modelBuilder);
                    
        }
    }
}

测试代码:

static void Demo7()
        {
            using(CodeFirstDbContext db = new CodeFirstDbContext())
            {
                //添加项目对象
                db.Projects.Add(new Project { ProjectName = "CRM系统", ProjectStartTime = DateTime.Now });
                db.Projects.Add(new Project { ProjectName = "HR系统",ProjectStartTime=DateTime.Now});
                db.Projects.Add(new Project { ProjectName= "数字触摸屏系统",ProjectStartTime=DateTime.Now });

                //保存项目对象
                db.SaveChanges();

                Project p1 = db.Projects.Where(d => d.ProjectName == "CRM系统").FirstOrDefault();
                db.Entry(p1).Reload();//预加载项目对象
                
                //添加员工对象
                p1.Employees.Add(new Employee { EmployeeID = "E001",EmployeeName="刘兵",EmployeeAge=22});
                p1.Employees.Add(new Employee { EmployeeID = "E002", EmployeeName = "王雪梅", EmployeeAge = 30 });
                p1.Employees.Add(new Employee { EmployeeID = "E003", EmployeeName = "张一山", EmployeeAge = 22 });
                
                //保存员工对象及项目对象和员工对象的关系
                db.SaveChanges();
            }

App.config文件配置:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
      <add name="CodeFirstDbContext" connectionString="Server=.\sqlexpress;Database=CodeFirst;integrated security=true" providerName="System.Data.SqlClient"/>
  </connectionStrings>
</configuration>

生成的数据结构:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值