-
Notifications
You must be signed in to change notification settings - Fork 859
Entity Relationship
中文 | English
FreeSql provides OneToMany, ManyToOne, ManyToMany, OneToOne, Parent, PgArrayToMany Six navigation attribute relationships.
What can navigation attributes do?
- 《Multi Tables》 Where(a => a.Parent.Parent.Name == "xx") Where(a => a.Childs.Any(b => b.title == "xxx"))
- 《Greed Loading》 Include/IncludeMany
- 《Lazy Loading》
- 《Parent-Child Relp》
- 《Cascade Saving》
- 《Cascade Deletion》
- 《AggregateRoot Repository》
OneToMany/ManyToMany supported types: ICollection<T>、List<T>、ObservableCollection<T>
//OneToMany
class Group
{
[Navigate(nameof(User.GroupId))]
public List<User> Users { get; set; }
//Find the GroupId property in User and associate it with this ENTITY.PrimaryKey
}
//ManyToOne
class User
{
public int GroupId { get; set; }
[Navigate(nameof(GroupId))]
public Group Group { get; set; }
//Find the GroupId property in THIS ENTITY and associate it with the Group.PrimaryKey
}
//ManyToMany
[Navigate(ManyToMany = typeof(TagSong))]
public List<Tag> Items { get; set; }
You can also use FluentApi to set the navigation relationship externally:
fsql.CodeFirst.ConfigEntity<YOUR_ENTITY>(a => a
.Navigate(b => b.roles, null, typeof(MANY_TO_MANY_MID_ENTITY))
.Navigate(b => b.users, "uid")
);
Note:
-
Set
Column(IsIgnore = true)
on Property, then the navigation property will be invalid -
The string set by Navigate is the property name of the type, NOT THE TABLE IR FIELD NAME.
Warm-up description: The navigation attribute configuration is loaded because it is necessary to solve the dead cycle reference. When the mutual reference relationship is very complex, it may cause the first use of navigation attributes to fail. The second time is enough. The solution is to warm up all entity classes when the program starts, and execute fsql.Select<object>().AsType(entityClass) in a loop;
//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; }
Non-primary key association rights support OneToMany/ManyToOne relationships and can only be valid when querying. (Cascade saving and deletion are not supported)
How to detect whether a navigation property is configured to take effect:
fsql.CodeFirst.GetTableByEntity(typeof(T))
.TestNavigate("roles")
.TestNavigate("users");
Method signature:
GetTableRef(string propertyName, bool isThrow);
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; }
//...
}
OneToOne, Require both sides to use the Navigate feature to associate with their own 'primary key'. (Supports cascading save and deletion)
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; }
}
more.. #1145
Tip: You can understand the content of this section a little. It is not necessary to master it. You can skip it.
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; }
}