简体   繁体   English

Entity Framework Core 中两个实体之间的一对多和一对一关系

[英]One to Many and one to one relation between two entity together in Entity Framework Core

I want to model Team and Players in Entity Framework Core 3.1.我想在 Entity Framework Core 3.1 中为TeamPlayers建模。 Each team has many players and every player has only one team.每支球队都有很多球员,每个球员只有一支球队。 Also, each team has one captain from the player list.此外,每支球队都有一名球员名单中的队长。 How can I write Fluent Api to the relation between Captain and Player (one to one)?我如何将 Fluent Api 写入CaptainPlayer之间的关系(一对一)?

public class Team
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    public int? CaptainId { get; set; }
    public Player Captain { get; set; }
    
    public ICollection<Player> Players { get; set; }
}

public class Player
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    public int TeamId { get; set; }
    public Team Team { get; set; }
}

I tried the following code我尝试了以下代码

builder.Entity<Team>()
    .HasOne(e => e.Captain)
    .WithOne()
    .HasForeignKey<Team>(e => e.CaptainId)
    .OnDelete(DeleteBehavior.Restrict);

builder.Entity<Team>()
    .HasMany(g => g.Players)
    .WithOne(s => s.Team)
    .HasForeignKey(s => s.TeamId);

But this code generates two one-to-many relationships ...但是这段代码生成了两个一对多的关系......

I've been trying something like this for the last few days, and after trying all sorts of Data Annotations and Fluent API nonsense, the cleanest solution I could come up with turned out to be very simple which requires neither.过去几天我一直在尝试这样的事情,在尝试了各种数据注释和 Fluent API 废话之后,我能想出的最干净的解决方案结果证明非常简单,两者都不需要。 It only requires adding a 'private' constructor to the Team class (or a 'protected' one if you're using Lazy Loading) into which your 'DbContext' object is injected.它只需要将“私有”构造函数添加到注入“DbContext”对象的 Team 类(如果使用延迟加载,则为“受保护”构造函数)。 Just set up your 'Team' and 'Player' classes as a normal one-to-many relationship, and with your database context now available from within the 'Team' entity, you can make the 'Captain' property simply return a query from the database using the Find() method.只需将您的“Team”和“Player”类设置为正常的一对多关系,并且您的数据库上下文现在可从“Team”实体中使用,您可以使“Captain”属性简单地从以下位置返回查询使用 Find() 方法的数据库。 The Find() method also makes use of caching, so if you call the getter more than once, it will only make one trip to the database. Find() 方法也使用缓存,因此如果多次调用 getter,它只会访问数据库一次。

Here is the documentation on this ability: https://docs.microsoft.com/en-us/ef/core/modeling/constructors#injecting-services这是有关此功能的文档: https : //docs.microsoft.com/en-us/ef/core/modeling/constructors#injecting-services

Note: the 'Captain' property is read-only.注意:“船长”属性是只读的。 To modify it, set the 'CaptainId' property.要修改它,请设置“CaptainId”属性。

class Team
{
    public Team() { }
    private MyDbContext Context { get; set; }
    // make the following constructor 'protected' if you're using Lazy Loading
    private Team(MyDbContext Context) { this.Context = Context; }

    public int ID { get; set; }
    public string Name { get; set; }
    public int? CaptainID { get; set; }
    public Player Captain { get { return Context.Players.Find(CaptainID); } }
}

class Player
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int TeamID { get; set; }
    public Team Team { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM