C# 实体框架核心:基于导航属性的集合

C# 实体框架核心:基于导航属性的集合,c#,entity-framework,collections,properties,entity-relationship,C#,Entity Framework,Collections,Properties,Entity Relationship,假设我们在EF Core中有以下多对多关系场景,具有以下导航属性: public class Request{ public HashSet<User> Users { get; set; } } 公共类请求{ 公共HashSet用户{get;set;} } 公共类用户{ 公共哈希集请求{get;set;} } 一个用户可能被简单地分配给多个请求,而一个请求可能有多个用户 现在,我想扩展该功能,以便每个用户都能够标记分配给他的请求: public class User

假设我们在EF Core中有以下多对多关系场景,具有以下导航属性:

public class Request{

    public HashSet<User> Users { get; set; }
}
公共类请求{
公共HashSet用户{get;set;}
}
公共类用户{
公共哈希集请求{get;set;}
}
一个用户可能被简单地分配给多个请求,而一个请求可能有多个用户

现在,我想扩展该功能,以便每个用户都能够标记分配给他的请求:

public class User{

    public HashSet<Request> Requests { get; set; }
    public Dictionary<long, bool> RequestsFlags { get; set; } //Request ID (long) and Flag (bool)
}
公共类用户{
公共哈希集请求{get;set;}
公共字典请求标签{get;set;}//请求ID(long)和标志(bool)
}
这样,我可以检查设置了哪个请求标志,并相应地更新UI。问题是,当然这两个集合必须始终彼此同步


有没有办法确保自定义集合总是与导航属性相符?

< p>如果标记请求的行为不需要持久化到用户请求表,那么您可以考虑将未映射的属性添加到被称为“标记”的请求实体。

这里的限制是,它仅与已加载的实体相关。不能在EF Linq查询中使用它。如果将用户和请求投影到视图模型,那么最好在视图模型中提供此属性

如果确实需要将标记状态持久化到UserRequest记录,则需要将加入实体引入关系:

public class User
{
    // User properties...

    // public virtual ICollection<Request> Requests { get; set; } = new List<Request>();
    public virtual ICollection<UserRequest> UserRequests { get; set; } = new List<UserRequest();
}
   
public class User
{
    // User properties...

    // public virtual ICollection<Users> Users { get; set; } = new List<User>();
    public virtual ICollection<UserRequest> UserRequests { get; set; } = new List<UserRequest();
}

public class UserRequest
{ 
    [Key, ForeignKey("User"), Column(Order=0)]
    public int UserId { get; set; }
    [Key, ForeignKey("Request"), Column(Order=1)]
    public int RequestId { get; set; }

    public bool Flagged { get; set; }

    public virtual User User { get; set; }
    public virtual Request Request { get; set; }
}
变成

foreach(var userRequest in user.UserRequests)
{
    var request = userRequest.Request;
    // do stuff..
}

. “附加数据可以存储在联接实体类型中,但为此,最好创建一个定制的CLR类型。”仅供参考EF Core 5中的示例文档显示,您可以同时使用原始导航和显式联接实体导航。我假设所有的导航都是可选的。因此,您可能需要
Request.Users
vs
User.UserRequests
感谢你们两位向我解释这一点,事实上,这是我描述的问题的完美解决方案。
public class User
{
    // User properties...

    // public virtual ICollection<Request> Requests { get; set; } = new List<Request>();
    public virtual ICollection<UserRequest> UserRequests { get; set; } = new List<UserRequest();
}
   
public class User
{
    // User properties...

    // public virtual ICollection<Users> Users { get; set; } = new List<User>();
    public virtual ICollection<UserRequest> UserRequests { get; set; } = new List<UserRequest();
}

public class UserRequest
{ 
    [Key, ForeignKey("User"), Column(Order=0)]
    public int UserId { get; set; }
    [Key, ForeignKey("Request"), Column(Order=1)]
    public int RequestId { get; set; }

    public bool Flagged { get; set; }

    public virtual User User { get; set; }
    public virtual Request Request { get; set; }
}
foreach(var request in user.Requests)
{
    // do stuff..
}
foreach(var userRequest in user.UserRequests)
{
    var request = userRequest.Request;
    // do stuff..
}