![](/img/trans.png)
[英]Creating composite primary key consisting off foreign keys in fluent API with ASP.NET 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.