I have a class "Project" that hat two lists one for "Employee" and one for "tool", when i build my project with only one of the lists the database updates with corrrect relation, if add the second list to the class entity framework can not figureout how to create the relation.
public class Project
{
public Guid Id { get; set; }
public List<Employee> RequiredEmployees {get;set;}
public List<Tools> RequiredTools {get;set;}
}
Public class Tool
{
public Guid Id { get; set; }
public string Name { get; set; }
public Project Project { get; set; }
public Guid ProjectId { get; set; }
}
I get the error "There are no primary or candidate keys in the referenced table" i hve tryed to map in ModelBuilder without success
modelBuilder.Entity<Employee>()
.HasRequired<Project>(s => s.Project)
.WithMany(g => g.Employee)
.HasForeignKey<Guid>(s => s.ProjectId);
any ideas ?
You have maneuvered yourself in several problems. The reported error is about the primary key. Furthermore you have problems specifying the one-to-many relations.
One-To-Many relations
Entity framework is easy if you follow the code first conventions For every deviation you need to tell entity framework about your deviations.
You planned to design a one-to-many between a
ProjectandTool: everyProjecthas zero or moreTools, everyToolbelongs to exactly oneProjectIf you follow the convention for one-to-many, you don't have to inform entity framework about this relation; entity framework will detect the relation by convention:
RequiredTools[4]mean?Consider using the proper naming conventions.:
Every Tool belongs to exactly one Project, using foreign key:
Similarly: Every Employee belongs to one Project
Or use many-to-many if an Employee can participate in several Projects:
And your Dbcontext:
This would be enough for entity framework to detect your relations and table names. I'd advice you to reconsider your decision to deviate from the code-first conventions.
However, if you really need to deviate your names you'll have to tell entity framework about your relations and table names:
Primary Keys
You chose not to use the conventional type for your primary Keys. The problem is that entity framework does not know how to fill your Id. You'll have to tell entity framework that you'll fill the values for the primary keys.
This is done by overriding DbContext.SaveChanges
There are also two SaveChangesAsync; we will override them to. Both procedures will call the same function that will generate your Id:
Function
GenerateIdswill get all items that need an Id and give it an Id. The objects that need an Id are all objects with state Added.However, the object in the DbContext that remembered all changes that need to be saved, only knows that these objects are DbEntityEntries. It does not know which property in your DbEntityEntry represents the primary key.
You could solve this using KeyAttribute. Get the added entry, ask for its type, ask the type for the property that has the KeyAttribute and set the value of this property.
This method has several disadvantages. Reflection is a fairly slow process, it depends on you giving all classes that need a GUID to add the KeyAttribute, it is not type safe, and you will only detect that your made mistakes at run-time.
It is much better to define that all your entity classes should implement an interface that defines the primary key:
If you forgot to implement your Id, your compiler will warn you. GenerateIds is now fairly simple: