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; }
}
Related
Say I want to model a relationship between users and auctions. A user can host an auction in which other users can bid in, while he can also bid in auctions of other users. So I want a User table, an Auction table with a foreign key reference to the User table, and an AuctionBidders table.
What do I have to add/change in the code below or in the OnModelCreating() method to make it work?
public class User
{
public int Id { get; set; }
public ICollection<Auction> Auctions { get; set; }
}
public class Auction
{
public int Id { get; set; }
public User Host { get; set; }
public ICollection<User> Bidders { get; set; }
}
Assuming that one action can have only have one Host, but the same user can be a Host for many auctions, you have to add relations for Host too
public class User
{
public int Id { get; set; }
[InverseProperty(nameof(Auction.Host))]
public ICollection<Auction> Hosts { get; set; }
public ICollection<Auction> Auctions { get; set; }
}
public class Auction
{
public int Id { get; set; }
public int HostId { get; set; }
[ForeignKey(nameof(HostId))]
[InverseProperty(nameof(User.Hosts))]
public User Host { get; set; }
public ICollection<User> Users { get; set; }
}
ef core 5+ will create the third table for you but I would prefer to add it explicetely since you have non standard db structrure
public class AuctionUser
{
[Key]
public int Id { get; set; }
public int AuctionId { get; set; }
[ForeignKey(nameof(AuctionId))]
[InverseProperty("Users")]
public virtual Auction Auction { get; set; }
public int UserId { get; set; }
[ForeignKey(nameof(UserId))]
[InverseProperty("Auctions")]
public virtual User User { get; set; }
}
I have 3 tables
User > Employee > Operator
There is a one to one relation on each other's end
public class User
{
[Key]
public int Id { get; set; }
public string Username { get; set; }
public DateTime? LoginDate { get; set; }
public bool IsActive{ get; set; }
public ICollection<Role> Roles { get; set; }
public virtual Employee Employee { get; set; }
}
public class Employee
{
[Key]
[ForeignKey("User")]
public int Id { get; set; }
public string Name{ get; set; }
public string Email { get; set; }
public int UserId { get;set; }
public virtual User User { get; set; }
public virtual Operator Operator{ get; set; }
}
public class Operator
{
[Key]
[ForeignKey("Employee")]
public int Id { get; set; }
public int EmployeeId {get;set;}
public EmployeeEmployee{ get; set; }
}
However this does create the one to one relation when i create a diagram in Sql Server MS to check the relations.
Problem is, when I'm just trying to insert data directly graphically from Sql it expects me to insert the primary key on Employee and Operator tables. Why aren't they automatic like the User one?
First, you don't need specify two variables to store same informations.
public int UserId { get;set; }
public int EmployeeId {get;set;}
already stored in Id. Not need to duplicate it.
Foreign keys doesn't use identity (doesn't generate values). So you need create User and then create an Employe where set the "User" property with user created before. (Main idea is that you need initialise reference to foreign key manually)
User user = new User{...};
Employee employe = new Employee{User = user, ...};
context.Add(employee);
context.SaveChanges();
Or maybe you will use hierarchy. (I don`t checked on 3 level, but on 2 this works perfectly).
public class User
{
[Key]
public int Id { get; set; }
public string Username { get; set; }
public DateTime? LoginDate { get; set; }
public bool IsActive{ get; set; }
public ICollection<Role> Roles { get; set; }
}
public class Employee : User
{
public string Name{ get; set; }
public string Email { get; set; }
}
public class Operator : Employee
{
}
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; }
}
Introduction
I am new to Entity Framework
I am using Code-first
Use-case
I have to following tables
[Table("TBL_UserVariant")]
public class UserVariant
{
[Key, Column(Order = 0)]
public int UserId { get; set; }
[Key, Column(Order = 1)]
public int VarId { get; set; }
public string Value { get; set; }
}
[Table("TBL_UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string eMail { get; set; }
}
I want TBL_UserProfile to refer a list of all TBL_UserVariant entries where TBL_UserProfile::UserId == TBL_UserVariant::UserId
The following is an example of my aim
[Table("TBL_UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string eMail { get; set; }
public UserVariant[] variants;
}
Where 'UserProfile::variants' should include a list of items where 'TBL_UserProfile::UserId == TBL_UserVariant::UserId'
Question
Is this directly possible using EF ? OR, should I implement a wrapper populating 'UserProfile::variants' ~manually~ ?
You have to just add a navigation property to the UserProfile entity.
[Table("TBL_UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string eMail { get; set; }
public virtual ICollection<UserVariant> UserVariants { get; set; }
}
The following is what you should need. EF will take care of the rest.
[Table("TBL_UserProfile")]
public class UserProfile
{
[Key]
public int UserId { get; set; }
public string eMail { get; set; }
public virtual ICollection<UserVariant> Variants { get; set; }
}
[Table("TBL_UserVariant")]
public class UserVariant
{
[Key]
public int VarId { get; set; }
public UserProfile User { get; set; }
public string Value { get; set; }
}
I think what you're asking for is that you want to have one UserProfile, mapped to Many UserVariants
In that case you'll need to add a collection to your UserProfile class.
public virtual ICollection<UserVariant> UserVariants { get; set; }
You'll also need to fix the [Key] property on the UserVariant class as I believe it should be on VarId. You can then just specify a navigation property
[Key]
public int VarId { get; set; }
public UserProfile User { get; set; }
Edit
As an aside, your naming conventions are all over the place. Don't prefix your table names with TBL_. Capitalise all your properties/Columns. e.g. Email not eMail
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 });
}