I'm having a bit of trouble getting my head around this relationship, and how to possibly setup cascade delete settings for it.
Note: it's possible for handles and attachments to exist without being used to make a tool
In short: an employee can mix-and-match handles and attachments to make tools, and then use a tool on a job they are assigned.
This diagram shows how the database is wired together ( feel free to suggest a better design )
This is how the models are setup, the Job model has a nullable reference to the tools FK (ToolId) so a job can exist without a tool.
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public List<Handle> Handles { get; set; }
public List<Attachment> Attachments { get; set; }
public List<Job> Jobs { get; set; }
}
public class Handle
{
public int HandleId { get; set; }
public string Material { get; set; }
public double ExpectedLife { get; set; }
public double LifetimeMaintenance { get; set; }
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
public List<Tool> Tools { get; set; }
}
public class Attachment
{
public int AttachmentId { get; set; }
public string Material { get; set; }
public string Type { get; set; }
public double ExpectedLife { get; set; }
public double LifetimeMaintenance { get; set; }
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
public List<Tool> Tools { get; set; }
}
public class Tool
{
public int ToolId { get; set; }
public string OperationSpeed { get; set; }
public int HandleId { get; set; }
public Handle Handle { get; set; }
public int AttachmentId { get; set; }
public Attachment Attachment { get; set; }
public List<Job> Jobs { get; set; }
}
public class Job
{
public int JobId { get; set; }
public string Name { get; set; }
public double EffortRequired { get; set; }
public int EmployeeID { get; set; }
public Employee Employee { get; set; }
public int? ToolId { get; set; }
public Tool Tool { get; set; }
}
This is how the DB context has been created. There is a cascade delete setting to set the tool FK in Jobs (ToolId) to null when a tool is deleted (so the job wont get deleted when its tool is deleted).
public class ToolsDbContext : DbContext
{
public ToolsDbContext(DbContextOptions<ToolsDbContext> options) : base(options)
{
}
public DbSet<Employee> employees { get; set; }
public DbSet<Handle> handles { get; set; }
public DbSet<Attachment> attachments { get; set; }
public DbSet<Tool> tools { get; set; }
public DbSet<Job> jobs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Tool>()
.HasMany(j => j.Jobs)
.WithOne(t => t.Tool)
.OnDelete(DeleteBehavior.SetNull);
}
}
Creating the migration works, but then updating the database fails with the following error:
Introducing FOREIGN KEY constraint 'FK_tools_handles_HandleId' on table 'tools' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
I'm not too sure how to understand this error.
Thinking it through:
Therefore I think the problem must be with deleting an employee, but I can't see why (yet?)...
So there is cascade paths deleting an employee, but I would expect this would all work based on the model setup as-is... So do I need to configure more cascade delete requirements in the dbcontext? If so, I'm not sure how it should be configured...
Note: without the employees model in the database, everything seems to work
SQL server doesn't allow to have multiple cascade paths to the same table in the database. In your case there are two of them for Tools:
All ways to fix the issue consist in setting DeleteBehavior.Restrict for one relationship or the other, for example:
etc...
You said:
There is a table of employees, where each employee has any number of handles, attachments and jobs
But your diagram establishes a direct link between an employee and a handle, one handle has many employees, and an employee has only one handle
Your statement is in conflict with your diagram
I think this modelling is wrong, from the database perspective. I think a job should have an employee. (If a job has multiple employees you'll need another table jobemployees that maps one job id to multiple employees.) A job has a tool, a tool has a handle and an attachment. I fail to see why deleting an employee should delete their jobs (if I fired someone the house he built while working for me still exists) but you can clean this up without using cascading constraints
Ultimately you can see in the diagram the cycle you've created. If deleting something at a 1 end deletes everything at the * end then deleting anything in your diagram starts a chain that takes a split path that comes back together. Removing the employee entity does indeed break this up
Ultimately an employee should not directly have a job, a handle or an attachment
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.