asp.net 实体框架中的可选一对一关系不会在我的SQL数据库中产生正确的外键-主键

rekjcdws  于 2023-04-22  发布在  .NET
关注(0)|答案(2)|浏览(112)

我的用例与我在教程中看到的几乎相同:我有一个类Slachtoffer和另一个类Schadeberekening。每个Schadeberekening必须有一个Slachtoffer,一个Slachtoffer可以有一个Schadeberekening
我尝试使用代码优先设置数据库,如下所示:

public class Slachtoffer
{
    public int Id { get; set; }

    public int? SchadeberekeningId{ get; set; }
    public Schadeberekening? Schadeberekening { get; set; }
}

public class Schadeberekening
{
    public int Id { get; set; }

    public int SlachtofferId { get; set; }
    public Slachtoffer Slachtoffer { get; set; }
}

modelBuilder.Entity<Slachtoffer>()
             .HasOne(s => s.Schadeberekening)
             .WithOne(ad => ad.Slachtoffer)
             .HasForeignKey<Schadeberekening>(ad => ad.SlachtofferId);

modelBuilder.Entity<Schadeberekening>()
             .HasOne<Slachtoffer>(a => a.Slachtoffer)
             .WithOne(sa => sa.Schadeberekening)
             .HasForeignKey<Slachtoffer>(sa => sa.SchadeberekeningId);

然而,当我查看创建的表时,只有在Slachtoffer表中,来自Schadeberekening的PK被认为是外键。在Schadeberekening表中,它只是一个“int”。
我该怎么解决这个问题?

q5iwbnjs

q5iwbnjs1#

在Schadeberekening中,它只是一个“int”。我如何解决这个问题?
我有一个如下的建议,删除OnModelCreating中的代码,并修改代码如下:
Slachtoffer:

public class Slachtoffer
    {
        public int Id { get; set; }

        [ForeignKey("Schadeberekening")]
        public int? SchadeberekeningId { get; set; }
        public virtual Schadeberekening? Schadeberekening { get; set; }
    }

Schadeberekening:

public class Schadeberekening
    {
        public int Id { get; set; }

        [ForeignKey("Slachtoffer")]
        public int SlachtofferId { get; set; }

        public virtual Slachtoffer Slachtoffer { get; set; }
    }

结果:

cbeh67ev

cbeh67ev2#

EF中的一对一关系可以通过两种方式进行配置。默认且最佳的可执行方式是在PK上连接两个表。您可以选择一个实体作为关系的根,相关表将共享该Id,该Id同时用作PK和FK返回到根。关系仍然可以为空(1到0或-1):

public class Slachtoffer
{
    public int Id { get; set; }

    public Schadeberekening? Schadeberekening { get; set; }
}

public class Schadeberekening
{
    [Key, ForeignHey(nameof(Slachtoffer))]
    public int Id { get; set; }

    public virtual Slachtoffer Slachtoffer { get; set; }
}

请注意,两个表中都没有FK字段,与Slachtoffer关联的Schadeberekening将共享相同的ID。如果您显式管理密钥设置,则Slachtoffer中的ID将被视为Identity,而在Schadeberekening中则不应如此,因为Slachtoffer将负责控制该ID。
配置1对1的第二种方法是使用显式FK。这将只存在于一个表或另一个表上,而不是两个表上。例如:

public class Slachtoffer
{
    public int Id { get; set; }

    public int? Schadeberekening { get; set; }
    public Schadeberekening? Schadeberekening { get; set; }
}

public class Schadeberekening
{
    public int Id { get; set; }

    public virtual Slachtoffer Slachtoffer { get; set; }
}

在这种情况下,你需要告诉EF关于1对1的关系,并且它应该使用指定的FK列在Slachtoffer表中定位FK。(理想情况下,这应该设置为实体中的影子属性)
如果配置为1对1关系,EF将尽最大努力遵守该约束,但在数据库级别,这是一个多对一的关系,除非您在Slacktoffer. SchadeberekeningId上添加唯一约束。(Code-first可以作为HasOne().WithOne()的一部分来执行此操作)在辅助表中没有另一个FK可以返回到父表,因为这可能会导致关系中断和无效。例如,如果我让A引用B,并返回到A的引用,如果我将A对C的引用更改为B对A的引用,则可能不会删除B对A的引用,或者不会创建C对A的引用。
在这里可以找到创建一对一关系的选项的良好细分:https://learn.microsoft.com/en-us/ef/core/modeling/relationships/one-to-one

相关问题