繁体   English   中英

ASP.NET EF CORE:由两个外键组成的复合键无法正确评估

[英]ASP.NET EF CORE: Composite key composed of two foreign keys not evaluating properly

编辑经过一些编辑后,我现在可以发布数据,但在搭建结构时遇到问题。 我的模型构建器现在感觉好多了,但还是有些不对劲

modelBuilder.Entity<Client>().HasMany(x => x.Machines).WithOne(x=>x.Client).HasForeignKey(x=>x.ClientID);
modelBuilder.Entity<Machine>().HasKey(x => new { x.ID, x.ClientID });
modelBuilder.Entity<MachineBob>().HasOne(x => x.Machine).WithMany(x => x.MachineBobData).HasForeignKey(x => new { x.MachineID, x.ClientID }).OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<MachineMixer>().HasOne(x => x.Machine).WithMany(x => x.MachineMixerData).HasForeignKey(x => new { x.MachineID, x.ClientID }).OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<MachineBob>().HasKey(c => new { c.TimeStamp, c.ClientID, c.MachineID });
modelBuilder.Entity<MachineMixer>().HasKey(x => new { x.TimeStamp, x.MachineID, x.ClientID });

结束 - 编辑

我正在尝试使用 EF Core 构建一个 Web 应用程序,该应用程序将允许客户端拥有任意数量的机器并记录其数据。 每台机器都可以是不同的类型,并且每种类型的机器都有一个唯一的表,因为它们记录不同的内容。 我能够毫无困难地创建 Client 和 Machine 对象,但是一旦我尝试将数据记录到我的 Machinexxx 数据表中,我就会遇到有关使用复合外键的问题。

CloudApp.Models

public class Client 
{
    [Required]
    [MaxLength(100)]
    public string ClientName { get; set; }
    [MaxLength(100)]
    [Key]
    public int ID { get; set; }
    [MaxLength(100)]
    // TODO: Automatically assign these email addresses as CLAIMS to allow the USER to see the CLIENT
    public List<String> Emails;
    public ICollection<Machine>? Machines { get; set; }
}

它与这里的Machine类有一对多的关系

public class Machine
{
    [MaxLength(50)]
    [Key]
    public int ID { get; set; }

    [MaxLength(100)]
    public string Factory { get; set; }
    [MaxLength(50)]
    public string Line { get; set; }

    [MaxLength(50)]
    public string MachineType { get; set; }
    [MaxLength(50)]
    public string MachineName { get; set; }
    [MaxLength(50)]
    public string Country { get; set; }
    [MaxLength(50)]
    public string City { get; set; }
    [MaxLength(25)]
    public int ZipCode { get; set; }
    [MaxLength(50)]
    public string Address { get; set; }

    [MaxLength(50)]
    public int ClientID { get; set; }
    public Client Client { get; set; } // Navivation property
    public List<MachineBob>? MachineBobData { get; set; } // Navivation property
    public List<MachineMixer>? MachineMixerData { get; set; }// Navivation property

它与(当前)两种可能的机器类型有一对多的关系

public class MachineBob 
{
    [MaxLength(50)]
    [XmlElement("TimeStamp")]
    public DateTime TimeStamp { get; set; }
    [XmlElement("Temperature")]
    [MaxLength(50)]
    public int Temperature { get; set; }
    [MaxLength(50)]
    [XmlElement("Heartbeat")]
    public Boolean Heartbeat { get; set; }

    [MaxLength(50)]
    [ForeignKey("MachineID")]
    public int MachineID { get; set; }
    public Machine Machine { get; set; }
    [MaxLength(50)]
    [ForeignKey("ClientID")]
    public int ClientID { get; set; }
    public Client Client { get; set; }
}

[XmlRoot("Root"),Serializable]
public class MachineMixer 
{
    [MaxLength(50)]
    [XmlElement("TimeStamp")]
    public DateTime TimeStamp { get; set; }
    [XmlElement("Temperature")]
    [MaxLength(50)]
    public int MixingRatio { get; set; }
    [MaxLength(50)]
    [XmlElement("Heartbeat")]
    public Boolean Heartbeat { get; set; }
    [XmlIgnore]

    [MaxLength(50)]
    public int MachineID { get; set; }
    public Machine Machine { get; set; }
    [MaxLength(50)]
    public int ClientID { get; set; }
    public Client Client { get; set; }
}

最后我的模型构建器看起来像这样(我的所有关系都在这里建立,由于它们的限制,我尽量不使用数据注释)

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
        base.OnModelCreating(modelBuilder);

        foreach (var foreignKey in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
        {
            foreignKey.DeleteBehavior = DeleteBehavior.Cascade;
        }

        modelBuilder.Entity<Client>().HasMany(x => x.Machines);

        modelBuilder.Entity<Machine>().HasOne(x => x.Client).WithMany(x => x.Machines).HasForeignKey(x => x.ClientID);
        modelBuilder.Entity<Machine>().HasKey(x => new { x.ClientID, x.ID });

        modelBuilder.Entity<Machine>().HasMany(x => x.MachineBobData).WithOne(x => x.Machine).HasForeignKey(x => new { x.MachineID, x.ClientID })OnDelete(DeleteBehavior.NoAction); 
        modelBuilder.Entity<Machine>().HasMany(x => x.MachineMixerData).WithOne(x => x.Machine).HasForeignKey(x => new { x.MachineID, x.ClientID }).OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<MachineBob>().HasKey(c => new { c.TimeStamp, c.ClientID, c.MachineID });

        modelBuilder.Entity<MachineMixer>().HasKey(x => new { x.TimeStamp, x.MachineID, x.ClientID });
}

我想要做的是让每一行都是一个数据条目,具有一个由MachineID, ClientID, Timestamp组成的唯一复合键。 但正如我在下面解释的那样,目前不可能......

正如我之前所说的,客户端和机器类的所有 CRUD 操作都可以正常工作。 但是 MachineBob 是令人难以置信的问题。 即使模型设计看到存在三个元素的复合键,但每当我尝试写入表时,我都会收到 SQL 错误。 很奇怪的是,只要我使用 ClientID = 1、MachineID = 1 和我想要的唯一时间戳,我就可以按预期编写。 但是,一旦我尝试通过写入 Client ID=X 来添加此 Machine BOB 的另一行或另一个实例,问题就会开始出现。

这是 SQL 异常,它似乎只有 ClientId 不唯一的问题。 但它是复合键的一部分,所以无论如何都不应该发生问题:

SqlException: INSERT 语句与 FOREIGN KEY 约束“FK_MachineBobs_Clients_ClientID”冲突。 数据库“aspnet-ProcessCloudApp-B3DBF3A9-F26C-41F4-B7D6-CC2D2782C266”、表“dbo.Clients”、“ID”列中发生冲突。 该语句已终止。

我想要一些关于我的模型构建的帮助,因为我对此感到最迷茫。

我的一部分认为问题也可能在于我如何考虑这个“MachineBob”数据模型。 也许最好在“Machine”和“MachineBob”之间建立一对一的关系并拥有ICollection<T>List<T>类型的所有属性

谢谢您的帮助。

我能够解决这个问题(只花了整周时间)。 我相应地修改了我的模型构建器,但也摆脱了 MachineBOB 中的“公共客户端客户端”。 即使我需要 ClientID,对象也没有直接相互连接。 这是供其他人参考的代码,他们认为值得进一步批评或供他们自己在这种半复杂关系中使用。

        modelBuilder.Entity<Client>().HasMany(x => x.Machines).WithOne(x=>x.Client).HasForeignKey(x=>x.ClientID);
        modelBuilder.Entity<Client>().HasKey(x => x.ID);
        modelBuilder.Entity<Machine>().HasKey(x => new { x.ID, x.ClientID });
        modelBuilder.Entity<MachineBob>().HasOne(x => x.Machine).WithMany(x => x.MachineBobData).HasForeignKey(x => new { x.MachineID, x.ClientID}).OnDelete(DeleteBehavior.NoAction);
        modelBuilder.Entity<MachineMixer>().HasOne(x => x.Machine).WithMany(x => x.MachineMixerData).HasForeignKey(x => new { x.MachineID, x.ClientID }).OnDelete(DeleteBehavior.NoAction);
        modelBuilder.Entity<MachineBob>().HasKey(c => new { c.TimeStamp, c.ClientID, c.MachineID });
        modelBuilder.Entity<MachineMixer>().HasKey(x => new { x.TimeStamp, x.MachineID, x.ClientID });

和班级

[XmlRoot("Root"),Serializable]
public class MachineBob 
{
    [MaxLength(50)]
    [XmlElement("TimeStamp")]
    public DateTime TimeStamp { get; set; }
    [XmlElement("Temperature")]
    [MaxLength(50)]
    public int Temperature { get; set; }
    [MaxLength(50)]
    [XmlElement("Heartbeat")]
    public Boolean Heartbeat { get; set; }

    [MaxLength(50)]
    [ForeignKey("MachineID")]
    public int MachineID { get; set; }
    public Machine Machine { get; set; }
    [MaxLength(50)]
    [ForeignKey("ClientID")]
    public int ClientID { get; set; }

暂无
暂无

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

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