34
实体关系
2881099 edited this page 2023-09-04 15:46:34 +08:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

中文 | English

FreeSql 提供 OneToMany, ManyToOne, ManyToMany, OneToOne, Parent, PgArrayToMany 六种导航属性关系。

导航属性能干什么?

导航属性进行多表查询非常方便lambda 表达式中直接使用导航对象点点点,舒服!!

自定义配置

OneToMany/ManyToMany 支持的类型ICollection<T>、List<T>、ObservableCollection<T>

//OneToMany
class Group
{
    [Navigate(nameof(User.GroupId))]
    public List<User> Users { get; set; }
    //在 User 查找 GroupId 属性,与 本实体.主键 关联
}

//ManyToOne
class User
{
    public int GroupId { get; set; }
    [Navigate(nameof(GroupId))]
    public Group Group { get; set; }
    //在 本实体 查找 GroupId 属性,与 Group.主键 关联
}

//ManyToMany
[Navigate(ManyToMany = typeof(TagSong))]
public List<Tag> Items { get; set; }

也可以使用 FluentApi 在外部设置导航关系:

fsql.CodeFirst.ConfigEntity<T>(a => a
    .Navigate(b => b.roles, null, typeof(TMid))
    .Navigate(b => b.users, "uid")
);

注意:

1、属性设置 Column(IsIgnore = true) 后,导航属性会失效

2、Navigate 设置的字符串是 类属性名,不是表 字段名!!!

预热说明:导航属性配置的加载,因为要解决死循环引用,当相互引用关系很复杂的时候,可能导致首次使用导航属性失败,第二次就可以了。解决办法可以程序启动时就预热所有实体类,循环执行 fsql.Select<object>().AsType(实体类);

与非主键关联

//OneToMany
[Navigate(nameof(User.GroupId), TempPrimary = nameof(Code))]
public List<User> Users { get; set; }

//ManyToOne
[Navigate(nameof(GroupId), TempPrimary = nameof(Group.Code))]
public Group Group { get; set; }

非主键关联权支持 OneToMany/ManyToOne 两种关系,并且只能在查询的时候有效。(不支持级联保存、级联删除)

检测导航属性

如何检测一个导航属性是否有效:

var tbref = fsql.CodeFirst
    .GetTableByEntity(typeof(T))
    .GetTableRef("Children", true);

GetTableRef(string propertyName, bool isThrow);

OneToOne

class User
{
    [Key]
    public int Id { get; set; }
    [Navigate(nameof(Id))]
    public UserExt Ext { get; set; }
    //...
}
class UserExt
{
    [Key]
    public int UserId { get; set; }
    [Navigate(nameof(UserId))]
    public User User { get; set; }
    //...
}

一对一,要求两边都使用 Navigate 特性与自身的【主键】关联。(支持级联保存,级联删除)

PgArrayToMany

class User
{
    public int[] RoleIds { get; set; }
    [Navigate(nameof(RoleIds))]
    public List<Role> Roles { get; set; }
}
class Role
{
    public int Id { get; set; }
    [Navigate(nameof(User.RoleIds))]
    public List<User> Users { get; set; }
}

更多资料:#1145

约定命名(无须指明 Navigate

提示:本节内容稍微了解即可,不是必须掌握的,可以跳过。

class Group
{
    public int Id { get; set; } //Id、GroupId、Group_id

    public List<User> AUsers { get; set; }
    public List<User> BUsers { get; set; }

    public int ParentId { get; set; } //ParentId、Parent_id
    public Group Parent { get; set; }

    public List<Group> Childs { get; set; }
}
class User
{
    public int Id { get; set; } //Id、UserId、User_id
    public UserExt Ext { get; set; }

    public int AGroupId { get; set; }
    public Group AGroup { get; set; }

    public int BGroupId { get; set; }
    public Group BGroup { get; set; }

    public List<Role> Roles { get; set; }
}
class UserExt
{
    public int UserId { get; set; }
    public User User { get; set; }
}
class Role
{
    public int Id { get; set; }
    public string Name { get; set; }

    public List<User> Users { get; set; }
}
class UserRole
{
    public int UserId { get; set; }
    public User User { get; set; }

    public int RoleId { get; set; }
    public Role Role { get; set; }
}