【问题标题】:Entity Framework Core: navigation property based collectionEntity Framework Core:基于导航属性的集合
【发布时间】:2021-05-17 22:59:03
【问题描述】:

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

public class Request{

    public HashSet<User> Users { get; set; }
}
public class User{

    public HashSet<Request> Requests { get; set; }
}

一个用户可能被简单地分配给多个请求,一个请求可能有多个用户。

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

public class User{

    public HashSet<Request> Requests { get; set; }
    public Dictionary<long, bool> RequestsFlags { get; set; } //Request ID (long) and Flag (bool)
}

这样我可以检查设置了标志的请求并相应地更新 UI。问题是这两个集合当然必须始终相互同步。

有什么办法可以保证自定义集合始终符合导航属性?

【问题讨论】:

标签: c# entity-framework collections properties entity-relationship


【解决方案1】:

如果标记请求的行为不需要持久化到 UserRequest 表中,那么您可以考虑将未映射的属性添加到名为“Flagged”的请求实体中。

public class Request
{
    // normal mapped properties.
  
    [NotMapped]
    public bool Flagged { get; set; }
}

这里的限制是它只与已经加载的实体相关。您不能在 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 request in user.Requests)
{
    // do stuff..
}

变成..

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

【讨论】:

  • 仅供参考,EF Core 5 docs.microsoft.com/en-us/ef/core/modeling/… 中的示例文档显示您可以同时拥有原始导航和显式连接实体导航。我假设所有导航都是可选的。所以你可能有Request.Users vs User.UserRequests
  • 感谢两位向我解释这一点,确实是我描述的问题的完美解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多