Entity Framework Two foreign keys as primary key - c#

So i am working with entity code firest and i have a user class that looks like this:
public class User
{
[Key]
public string Username { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime LastModified { get; set; }
}
I am trying to make a "friends table" and no matter what i come up with I get an error on the db creation. This is what I Currently have in the Friends Class:
public class Friend
{
[Key, ForeignKey("User")]
public virtual User MyUser { get; set; }
[Key,ForeignKey("User")]
public virtual User MyFriend { get; set; }
public bool IsAccepted { get; set; }
}
this is the error i get:
The ForeignKeyAttribute on property 'MyUser' on type 'Core.Model.Friend' is not valid. The foreign key name 'User' was not found on the dependent type 'Core.Model.Friend'. The Name value should be a comma separated list of foreign key property names.
What am I missing?

You need to use the Column attribute. Normally I would use something like this:
public class Friend
{
[Key]
[Column(Order = 0)]
public int MyUserId { get; set; }
[Key]
[Column(Order = 1)]
public int MyFriendId { get; set; }
[ForeignKey("MyUserId")]
public virtual User MyUser { get; set; }
[ForeignKey("FriendId")]
public virtual User MyFriend { get; set; }
public bool IsAccepted { get; set; }
}
I'm not sure what would happen if you map the Column attribute directly to the navigation property. You can try it if you like and see what happens.. but the above generally works for me.
Alternatively, if you change to use fluent mapping, you can do something like this:
HasKey(u => new { u.MyUserId , u.MyFriendId });

Related

How to reference two users(each with a different role) in an Entity Framework Class

I have one entity that relates to two users in the AspNetUsers table:
User with the role of Tenant
User with the role of Landlord
Property (Created with entity framework)
I can't figure out how to relate 1 tenant and 1 landlord with 1 property when creating foreign key relationships in my property context. To do this I would need to implement two foreign keys in my property class but they would both be a UserID from Identity. That doesn't seem right though and I can't get my head around it. Below is what the beginning of my Property.cs file would look like.
public class Property
{
[ScaffoldColumn(false)]
public string PropertyID { get; set; }
[Key, ForeignKey("User")]
public string LandlordId { get;set; }
[Key, ForeignKey("User")]
public string TenantId { get;set; }
//other fields
public virtual ApplicationUser User { get;set; }
}
You have two ways to do this:
Keep your current model, and ensure you set up the navigational properties correctly:
public class Property
{
public int PropertyId { get; set; }
public int TenantId { get; set; }
public int LandlordId { get; set; }
public User Tenant { get; set; }
public User Landlord { get; set; }
}
Notice that, since this correctly follows convention over configuration, there's no need for applying [ForeingKey].
This is going to represent a bigger change in your application. You would need to introduce a Landlord and a Tenant entity:
public class Landlord
{
...
public int UserId { get; set; }
public User User { get; set }
}
public class Tenant
{
...
public int UserId { get; set; }
public User User { get; set }
}
And then map those to the Property entity:
public class Property
{
public int PropertyId { get; set; }
public int TenantId { get; set; }
public int LandlordId { get; set; }
public Tenant Tenant { get; set; }
public Landlord Landlord { get; set; }
}
Now, which of those approaches make more sense in your business domain and in this application is up to you to decide.

Can't set primary key and foreign key on one column

So I try to create some ASP.NET project with EF Core.
I want to set propert of one entity as primary key and foreign key to another entity. The relationship is 0..1 - 1. I use DataAnnotations:
public class OfficeAssignment
{
[Key, ForeignKey("InstructorID")]
public int InstructorID { get; set; }
public Instructor Instructor { get; set; }
public string Location { get; set; }
}
But I keep getting column InstructorID as PK and InstructorID1 as FK... Any ideas, why EF behaves like that and how can I achieve my goal?
You should follow convention over configuration as much as you can. An OfficeAssignment entity should have an OfficeAssignmentId PK, like this:
public class OfficeAssignment
{
public int OfficeAssignmentId { get; set; }
//Notice that Id does not have an uppercase D
public int InstructorId { get; set; }
public string Location { get; set; }
public Instructor Instructor { get; set; }
}
However, if you don't want to follow normal conventions, the name of the property that goes in the ForeignKey attribute is the opposite of where it's declared:
public class OfficeAssignment
{
[Key, ForeignKey("Instructor")]
public int InstructorId { get; set; }
public string Location { get; set; }
public Instructor Instructor { get; set; }
}
And, if you want to keep it compile-time safe:
public class OfficeAssignment
{
[Key, ForeignKey(nameof(Instructor))]
public int InstructorId { get; set; }
public string Location { get; set; }
public Instructor Instructor { get; set; }
}
It's enough to set primary key attribute([Key]) in the OfficeAssignment class and in Instructor class we need to set such attribute:
[InverseProperty("Instructor")]
on collection of CourseAssignments. That will work as desired.

The property 'Dish_ID' cannot be used as a key property on the entity

I'm trying to add some entities using EntityFramework.
I need the same model as in image
I created two classes:
public class PriceOfDish
{
[Key]
public virtual List<Dish> Dish_ID { get; set; }
[Key]
public DateTime DateTime { get; set; }
public decimal Price { get; set; }
}
public class Dish
{
[Key]
public int Dish_ID { get; set; }
public string DishName { get; set; }
public string Description { get; set; }
public virtual FoodCategory FoodCategory_ID { get; set; }
public virtual Feature Feature_ID { get; set; }
public virtual ICollection<OrderedDishes> Orders { get; set; }
}
Using FluentAPI trying to set primary keys:
builder.Entity<PriceOfDish>()
.HasKey(t => new {t.Dish_ID, t.DateTime});
During updating DB i get error message: "The property 'Dish_ID' cannot be used as a key property on the entity 'testFOef.PriceOfDish' because the property type is not a valid key type. Only scalar types, string and byte[] are supported key types.".
But why? Can you explain this to me? Thanks for any help
Like the error say you are using a List<Dish> as a type for your primary key. You must use an scalar type (value type) as usual or byte[].
For you, the solution is to create a proprerty Dish_ID with int type.
public class PriceOfDish
{
[Key]
public int Dish_ID { get; set; }
[Key]
public DateTime DateTime { get; set; }
[ForeignKey("Dish_Id")]
public virtual Dish Dish { get; set; }
public decimal Price { get; set; }
}
you're trying to set a List<Dish> Dish_ID as a key of a table.
But this is not supported. It doesn't make much sense either. list of Dishes that will have a single Price? I think you want to put int Dish_ID there

Foreign key invalid with Entity Framework

So i am trying to create a table with a foreign key, but it always says that it cannot find the foreign key. heres the code:
public class Tecnologies
{
[Key]
public int TecId { get; set; }
[Required]
public String Name { get; set; }
}
this one works, then i try to create this one:
public class UserTecnologies
{
[Key]
public int UserTecId { get; set; }
[ForeignKey("Id")]
public UserProfile User { get; set; }
[ForeignKey("TecId")]
public virtual Tecnologies Tecnology { get; set; }
[Required]
public int Rating { get; set; }
}
and it gives me the error :
The ForeignKeyAttribute on property 'Tecnology' on type 'ESW_CloddOffice.Models.UserTecnologies' is not valid. The foreign key name 'TecId' was not found on the dependent type 'ESW_CloddOffice.Models.UserTecnologies'. The Name value should be a comma separated list of foreign key property names.
The names are correct, what am i missing ?
Okay, i found what i was doing wrong. Heres the correct code:
public class UserTecnologies
{
[Key]
public int UserTecId { get; set; }
[ForeignKey("UserProfile")]
public virtual int UserProfileId { get; set; }
[ForeignKey("Tecnology")]
public virtual int TecnologyId { get; set; }
public virtual Tecnologies Tecnology { get; set; }
public virtual UserProfile UserProfile { get; set; }
[Required]
public int Rating { get; set; }
}
Was creating the foreign key the wrong way .
The ForeignKey attribute requires that an actual property on the entity match the name you pass in. It doesn't just tell EF what to call the key at the database level.
You either need to actually add a TecId property:
public int TecId { get; set; }
Or use fluent configuration, instead:
modelBuilder.Entity<UserTechnologies>()
.HasRequired(c => c.Technology)
.WithMany()
.Map(m => m.MapKey("TecId"));

Two same class types in entity framework class issue

I am implementing feature that allows users to follow each other.
I have database tables:
User{UserId, FirstName, LastName etc.}
Followings{FollowerUserId, FollowingUserId, CreatedOnDate etc.}
So I added EF class:
public class Follow
{
[Key, Column(Order = 1)]
public Guid FollowerUserId { get; set; }
[Key, Column(Order = 2)]
public Guid FollowUserId { get; set; }
public DateTime CreatedOnDate { get; set; }
public virtual User Follower { get; set; }
public virtual User Following { get; set; }
}
The last two virtual properties couse issue.
When I call:
var model = con.Follows.Where(x => x.FollowerUserId == uid);
I get following exception:
Invalid column name 'Following_UserId'.
The issue is probably caused because of two User objects in one class. Any idea how to workaround this?
UPDATE
public class User
{
public Guid UserId { get; set; }
...
public virtual ICollection<Follow> Following { get; set; }
public virtual ICollection<Follow> Followers { get; set; }
}
I think the reason is that the foreign key properties (FollowerUserId and FollowUserId) and navigation properties (Follower and Following) do not respect the naming conventions so that EF is unable to recognize the first properties as foreign keys. You can fix the problem by specifying the FK properties explicitly using the [ForeignKey] attribute:
public class Follow
{
[Key, Column(Order = 1), ForeignKey("Follower")]
public Guid FollowerUserId { get; set; }
[Key, Column(Order = 2), ForeignKey("Following")]
public Guid FollowUserId { get; set; }
public DateTime CreatedOnDate { get; set; }
public virtual User Follower { get; set; }
public virtual User Following { get; set; }
}
Edit
A least the second property doesn't respect the naming convention, the first one looks OK. So, alternatively you can fix the problem by renaming the second FK property FollowUserId into:
public Guid FollowingUserId { get; set; }
...because the navigation property is called Following.
Edit 2
About your UPDATE: You need to add the [InverseProperty] attribute to tell EF which navigation properties belong together:
public class Follow
{
[Key, Column(Order = 1), ForeignKey("Follower")]
public Guid FollowerUserId { get; set; }
[Key, Column(Order = 2), ForeignKey("Following")]
public Guid FollowUserId { get; set; }
public DateTime CreatedOnDate { get; set; }
[InverseProperty("Followers")] // refers to Followers in class User
public virtual User Follower { get; set; }
[InverseProperty("Following")] // refers to Following in class User
public virtual User Following { get; set; }
}

Categories

Resources