I'm currently using Entity Framework 7.0.0-beta3 and am trying to create a many-to-many relationship between two tables. For that I'm using the syntax from The answer of this question, minus the ICollections:
public class Permissions
{
public Guid PermissionId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class relUserPermissions
{
public string UserId { get; set; }
public ApplicationUser User { get; set; }
public Guid PermissionId { get; set; }
public Permissions Permission { get; set; }
}
ApplicationUser is referring to the AspNetUsers Table. Using the kpm migration tool, this will create the relUserPermissions Table with foreign keys to both AspNetUsers and Permissions.
As I'm trying to access this via LINQ, I need to add the relation to the Database Context, using public DbSet<relUserPermissions> relUserPermission { get; set; }. But once I add that line, the foreign key to Permissions is no longer generated, the foreign key to AspNetUsers still is.
For creating relationship you have to provide it on both the table,
try this:
public class Permissions
{
public Guid PermissionId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public IList<relUserPermissions> relUserPermission {get; set;}
}
public class relUserPermissions
{
public string UserId { get; set; }
public ApplicationUser User { get; set; }
public Guid PermissionId { get; set; }
public Permissions Permission { get; set; }
}
add this property in Permissions class
public Ilist<relUserPermisions> relUserPermission {get; set;}
While it is a bit annoying, having to do that, for now I was able to solve the problem by renaming Permissions.PermissionId to Permissions.Id. Not a great solution and I have no clue why this affects anything (I added PermissionId as a key via Fluent API before), but it's working.
Add Navigation property as shown bleow
public ApplicationUser User { get; set; }
public Guid PermissionId { get; set; }
public Permissions Permission { get; set; }
public virtual Permissions Permission { get; set; }
Related
Earlier I had the following classes with relationship
[Table("User")]
public class User
{
// Base properties
[Key]
public int UserId { get; set; }
public string Name { get; set; }
// Relationships
public ICollection<UserRole> UserRoles { get; set; }
}
[Table("UserRole")]
public class UserRole
{
// Base properties
[Key]
public int UserRoleId { get; set; }
public string Name { get; set; }
// Relationships
public int UserId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
}
EF Core was able to map this to SQL as intended which gave two tables
User - UserId (PK), Name
UserRole - UserRoleId (PK), Name, UserId (FK)
Later I wanted to add a way to verify the records and the verifiers are coming from the User table itself. The below is how the verification implemented:
[Table("User")]
public class User
{
// Base properties
[Key]
public int UserId { get; set; }
public string Name { get; set; }
// Relationships
public ICollection<UserRole> UserRoles { get; set; }
// Verification
public int? VerifierId { get; set; }
[ForeignKey("VerifierId")]
public User Verifier { get; set; }
}
[Table("UserRole")]
public class UserRole
{
// Base properties
[Key]
public int UserRoleId { get; set; }
public string Name { get; set; }
// Relationships
public int UserId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
// Verification
public int? VerifierId { get; set; }
[ForeignKey("VerifierId")]
public User Verifier { get; set; }
}
The above setup is giving the following exception while adding the migration: Unable to determine the relationship represented by navigation property 'User.UserRoles' of type 'ICollection<UserRole>'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
However removing the below property in the UserRole table makes the migration possible:
ForeignKey("VerifierId")]
public User Verifier { get; set; }
But it is not what I want. I want the foreign key kept as well. How to make this possible? and why this is not allowed at the first place?
The problem here is that EF does not know which FK (UserId or VerifierId) should be mapped to the UserRoles property of the User class.
You need to define which foreign key should be used
[InverseProperty(nameof(UserRole.User))]
public ICollection<UserRole> UserRoles { get; set; }
See the documentation here
https://learn.microsoft.com/en-us/ef/core/modeling/relationships
I am new to Entity Framework. I am using database first approach and I don't auto generate entity files. I have 3 tables User, Database and UserDatabase. The table UserDatabase has a many-to-many relationship with both User and Database. I am not sure how to build this relationship in my class.
public class Database
{
[Key]
public int DatabaseId { get; set; }
public string DatabaseName { get; set; }
}
public class User
{
[Key]
public int? UserID { get; set; }
[Required]
public string Name{ get; set; }
}
public class UserDatabase
{
[Key]
public int UserID { get; set; }
[ForeignKey("UserID")]
public virtual User Users{ get; set; }
public int DatabaseID { get; set; }
[ForeignKey("DatabaseID")]
public virtual Database Database { get; set; }
}
This is my current code. If I add one database per user it is working fine. But if I add multiple, it throws multiplicity constraint violation error. Please help.
I have found out the mistake. In the link table "UserDatabase" I have mentioned UserID as the primary key and that is why I am not able to add multiple records. It should be a composite key and I have marked both user and database as key and given the order. I have changed it to
public class UserDatabase
{
[Key, Column(Order=0)]
public int UserID { get; set; }
[ForeignKey("UserID")]
public virtual User Users{ get; set; }
[Key, Column(Order=1)]
public int DatabaseID { get; set; }
[ForeignKey("DatabaseID")]
public virtual Database Database { get; set; }
}
Try modifying your UserDatabase to following:
public class UserDatabase
{
[ForeignKey("Users")]
public int UserID { get; set; }
[ForeignKey("Database")]
public int DatabaseID { get; set; }
public virtual User Users{ get; set; }
public virtual Database Database { get; set; }
}
I have two entities which I want to be connected 1:1 relationship. User is principal and UserActivation is dependent, but I have no idea how that works.
public class User
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Lastname { get; set; }
public string Username { get; set; }
public virtual UserActivation UserActivation { get; set; }
}
public class UserActivation
{
[Key]
public Guid Id { get; set; }
public Guid UserId { get; set; }
public bool Active { get; set; }
public virtual User User { get; set; }
}
I have tried to remove 'virtual' keyword, have tried to add ForeignKey("UserId") or ForeignKey("User"), I've even tried to make [Key, ForeignKey("User") and none of them helped me. I want to make 1:1 relationship using only dataannotations. Any help is really appreciated. Also my both classes has their own PKs.
Foreign keys are not supported for 1:1 try:
public class User
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Lastname { get; set; }
public string Username { get; set; }
public virtual UserActivation UserActivation { get; set; }
}
public class UserActivation
{
[Key]
[ForeignKey("User")]
public Guid Id { get; set; }
public bool Active { get; set; }
public virtual User User { get; set; }
}
Unable to determine the principal end of an association between the types ‘Model.PersonPhoto’ and ‘Model.Person’. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
Julie Lehrman discusses this in her Code First book:
"This problem is most easily solved by using a ForeignKey annotation
on the dependent class to identify that it contains the foreign key.
When configuring one-to-one relationships, Entity Framework requires
that the primary key of the dependent also be the foreign key. In our
case PersonPhoto is the dependent and its key, PersonPhoto.PersonId,
should also be the foreign key. Go ahead and add in the ForeignKey
annotation to the PersonPhoto.PersonId property, as shown in Example
4-21. Remember to specify the navigation property for the relationship
when adding the ForeignKey annotation."
This post is quite old so I thought I'd post the EF 6 solution
Try this...
public class User
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Lastname { get; set; }
public string Username { get; set; }
public virtual UserActivation UserActivation { get; set; }
}
public class UserActivation
{
[ForeignKey("User")]
public Guid Id { get; set; }
public Guid UserId { get; set; }
public bool Active { get; set; }
public virtual User User { get; set; }
}
I have 3 entities:
public class AspNetUser
{
public string Id {get; set;}
}
public class Event
{
public int Id {get; set;}
}
public class UserEvent
{
[Column(Order=0), Key, ForeignKey("AspNetUsers")]
public string UserId { get; set; }
[Column(Order=1), Key, ForeignKey("Events")]
public int EventId { get; set; }
public DateTime EnrolTime { get; set; }
public virtual AspNetUser User { get; set; }
public virtual Event Event { get; set; }
}
As you can see that, the UserEvent is just a relationship table which has both UserId and EventId from 2 tables.
My question is:
Is annotation enough to tell EF to create the 2 foreign keys? Or I have to also use Fluent API to do it in the OnModelCreating() method in the DbContext class? Or I have to create a configuration class to do so?
I saw something in this post(it makes me confused):
Entity Framework Multiple Column as Primary Key by Fluent Api
ForeignKey("X")
I guess the X should be the table name rather than the entity's name, right?
E.g. X should be the AspNetUsers(which is in the database), rather than AspNetUser which is the entity name.
Thank you.
Yes, it's enough using Data Annotations, but the problem is you need to specify in the ForeignKey attribute the name of navigation property`that represents the relationship it is a foreign key for:
public class UserEvent
{
[ Key,Column(Order=0), ForeignKey("User")]
public string UserId { get; set; }
[ Key,Column(Order=1), ForeignKey("Event")]
public int EventId { get; set; }
public DateTime EnrolTime { get; set; }
public virtual AspNetUser User { get; set; }
public virtual Event Event { get; set; }
}
Alternatively, you can apply the ForeignKey annotation to the navigation property and tell it which property is the foreign key for the relationship:
public class UserEvent
{
[Key,Column(Order=0)]
public string UserId { get; set; }
[Key,Column(Order=1)]
public int EventId { get; set; }
public DateTime EnrolTime { get; set; }
[ForeignKey("UserId")]
public virtual AspNetUser User { get; set; }
[ForeignKey("EventId")]
public virtual Event Event { get; set; }
}
public class UserEvent
{
public DateTime EnrolTime { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual AspNetUser User { get; set; }
public int EventId { get; set; }
[ForeignKey("EventId")]
public virtual Event Event { get; set; }
}
I have these classes
public class SecretQuestion
{
[Key]
public int SecretQuestionId { get; set; }
[Required]
public string Caption { get; set; }
}
public class UserSecretQuestion
{
public SecretQuestion SecretQuestion { get; set; }
public User User { get; set; }
[Required]
public string Answer { get; set; }
}
public class User
{
[Key]
public int UserId { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
}
I want UserSecretQuestion to be a join table holding the user's Answer. The problem is that EF5 won't create this table for me because it claims I need a key on that table.
so of course putting public int Id { get; set; } in there will fix it but that puts a field I don't need in my database.
Is there a way to make this work properly so that the secretquestionid and userid foreign keys form a composite key for the usersecretquestion table.
I note that there are a few questions on here that talk about many to many relationships but none (that I can find) talk about this kind of relationship where the entity has extra data e.g. 'Answer'.
First you have to add SecretQuestionId and UserId as properties to the UserSecretQuestion class.
public class UserSecretQuestion
{
[Key, ForeignKey("SecretQuestion")]
public int SecretQuestionId { get; set; }
[Key, ForeignKey("User")]
public int UserId { get; set; }
[Required]
public string Answer { get; set; }
public SecretQuestion SecretQuestion { get; set; }
public User User { get; set; }
}
You then have to override the OnModelCreating method in your DbContext class and tell Entity Framework to use composite keys for the join table.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Set composite keys
modelBuilder.Entity<UserSecretQuestion>().HasKey(k => new { k.SecretQuestionId, k.UserID });
}