暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【EntityFramework系列】入门湿货(二)管理实体关系示例

歆视界 2018-04-22
187

关于Entity Framwork之前已经在EntityFramework系列内容中介绍了两篇。码农们应该都知道数据库理论中的多样性关系,即一对一关系、一对多关系、多对多关系,今天我们就来介绍一下用Entity Framework的CodeFirst如何实现。以下接着使用之前的源码示例继续进行。

一对一关系

这种关系,不常用到,本身在数据库设计中也不常用,遇到这种情况一般就一个表记录完事儿。但是如果遇到一个实体存在可选数据,那么就可以选择这种一对一的关系设计。

接着之前代码示例,我们创建一个Student实体。一个用户可以是学生,也可以不是学生,我们把用户的学生信息单独记录在Student表中。


public class Student
{
    /// <summary>
    /// 用户ID
    /// </summary>
    public int UserId { get; set; }
    /// <summary>
    /// 用户
    /// </summary>
    public virtual User User { get; set; }
    /// <summary>
    /// 学校名
    /// </summary>
    public string CollegeName { get; set; }
    /// <summary>
    /// 入学时间
    /// </summary>
    public DateTime EnrollmentDate { get; set; }
}


因为一对一关系,所以我们需要在之前的User实体中也添加一行学生对象的记录(这里使用virtual关键字的目的是什么呢?没错,懒加载):


public virtual Student Student { get; set; }



然后我们需要创建一个学生伙伴类,来指定主键、外键,设置属性等。然后在数据库上下文的OnModelCreating方法使用学生伙伴类。


public class StudentMap : EntityTypeConfiguration<Student>
{
    public StudentMap()
    {
        //设置外键关系
        HasRequired(s => s.User).WithOptional(p => p.Student);
        //指定主键
        HasKey(s => s.UserId);
        //设置学校名的属性(字符长度50,不可为空)
        Property(s => s.CollegeName).HasMaxLength(50).IsRequired();
    }
}


Main方法中,创建数据库的代码如下:


using (var context = new TestContext())
{
    //如果数据库不存在时则创建
    context.Database.CreateIfNotExists();

    var student = new Student
    {
        CollegeName = "XX大学",
        EnrollmentDate = DateTime.Parse("2000-11-11"),
        User = new User
        {
            Name = "张三",
            BirthDay= DateTime.Parse("1980-01-01")
        }
    };
    context.Students.Add(student);
    context.SaveChanges();
}


编译运行,你就能看到数据库里的表结构以及示例数据。

一对一关系就介绍到这里。接下来介绍一对多关系。

一对多关系

继续针对User实体,实际场景中,用户一般有分角色:管理员用户角色、普通用户角色等。这里只用两个角色来做示例,先介绍一个用户只有一个角色、一个角色可以包含多个用户的情况,即设定用户角色为一对多关系。用户角色的多对多关系,再后面进行介绍。

首先,添加一个用户角色实体类:


public class UserActor
{
    public int UserActorId{ get; set; }

    public string ActorName { get; set; }
    //集合属性。表示一个角色可以有多个用户。(懒加载)
    public virtual ICollection<User> Users { get; set; }
}


接下来,修改之前创建的用户实体类:


public class User
{
    public int UserId { get; set; }

    public string Name { get; set; }

    public DateTime BirthDay { get; set; }

    public int? ActorId { get; set; }

    public virtual UserActor UserActor { get; set; }
}


此处使用了可空类型字段,说明外键可为null。

接下来创建用户角色的伙伴类:


public class UserActorMap : EntityTypeConfiguration<UserActor>
{
    public UserActorMap()
    {
        HasMany(dt => dt.Users)
            .WithOptional(d => d.UserActor)  指定实体关系
            .HasForeignKey(d => d.ActorId)   指定外键
            .WillCascadeOnDelete(false);     指定约束的删除规则
    }
}


Main方法中,创建数据库的代码如下:


using (var context = new TestContext())
{
    //如果数据库不存在时则创建
    context.Database.CreateIfNotExists();

    var userActor = new UserActor
    {
        ActorName = "管理员",
        Users = new List<User> { new User { Name = "张三", BirthDay = new DateTime(2001, 2, 2) } }
    };
    var userActor2 = new UserActor
    {
        ActorName = "普通用户",
        Users = new List<User> { new User { Name = "李四", BirthDay = new DateTime(1998, 5, 5) } }
    };
    context.UserActors.Add(userActor);
    context.UserActors.Add(userActor2);
    context.SaveChanges();
}


不要忘了在Context类中添加UserActor的DbSet,还有在OnModelCreating上添加UserActorMap的配置类。

编译运行,你就能看到数据库里的表结构以及示例数据。

一对多关系就介绍到这里。接下来介绍多对多关系。

多对多关系

接下来介绍用户角色的多对多关系。

参考一对多关系,不难想出如何修改一对多的用户角色关系为多对多的用户角色关系。

修改用户实体:


public class User
{
    public User()
    {
        UserActors = new HashSet<UserActor>();
    }


    public int UserId { get; set; }

    public string Name { get; set; }

    public DateTime BirthDay { get; set; }

    //public int? ActorId { get; set; }
    public virtual UserActor UserActor { get; set; }
    public virtual ICollection<UserActor> UserActors { get; set; }

}


同时我在用户角色实体中也添加了构造函数,用来初始化用户集合。


public UserActor()
{
    Users = new HashSet<User>();
}


修改用户角色伙伴类:


public UserActorMap()
{
    //HasMany(dt => dt.Users)
    //    .WithOptional(d => d.UserActor)  指定实体关系
    //    .HasForeignKey(d => d.ActorId)   指定外键
    //    .WillCascadeOnDelete(false);     指定约束的删除规则

    HasMany(p => p.Users)
        .WithMany(c => c.UserActors)
        .Map(m =>
            {
                m.MapLeftKey("UserId");
                m.MapRightKey("UserActorId");
            });
}


Main方法中,创建数据库的代码如下:


using (var context = new TestContext())
{
    //如果数据库不存在时则创建
    context.Database.CreateIfNotExists();

    var user = new User
    {
        Name = "张三",
        BirthDay = new DateTime(2001, 2, 2)
    };
    var user2 = new User
    {
        Name = "李四",
        BirthDay = new DateTime(1998, 5, 5)
    };
    context.Users.Add(user);
    context.Users.Add(user2);
    var userActor = new UserActor
    {
        ActorName = "普通用户"
    };
    userActor.Users.Add(user);
    context.UserActors.Add(userActor);
    context.SaveChanges();
}


编译运行,你就能看到数据库里的表结构以及示例数据。

从数据库中,可以看到Entity Framework在处理多对多关系的时候,会自动创建一个中间表(比如上面示例,数据库中创建的UserActorUsers表),用来记录多对多的关系。该中间表的名称,可以在伙伴类中设定。


以上就是今天介绍的Entity Framework管理三种实体关系的源码示例及简单说明。

下期预告:【EntityFramework系列】入门湿货(三)数据迁移。

文章转载自歆视界,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论