Mapping EF Foreign key with different names - c#

I have the below domain classes:
public class Product
{
public Guid? Id { get; set; }
public string? Name { get; set; }
}
public class Order
{
public Guid? Id { get; set; }
public string? Address{ get; set; }
public Guid? ProductId{ get; set; }
}
I am not using navigation properties for setting the foreign key but am doing it as below:
public void Configure(EntityTypeBuilder<Order> builder)
{
builder.HasOne<Product>()
.WithMany()
.HasForeignKey(c => c.ProductId);
}
My problem when I do the update-database, it says that the field ProductId does not exist. This is because it named as Id in table product but in table order it is named as ProductId. Is there a way to map the foreign key with a different name?

Modify the Product class
public class Product
{
public Guid? Id { get; set; }
public string? Name { get; set; }
public ICollection<Order> Orders {get; set;}
}
The relationship will work properly.
Reference: Relationships

Related

Entity Framework - Foreign keys and Navigation Properties

I need your help understanding relationships between tables. I´m having a hard time trying to understand the usage/need of using navigation properties with foreign key properties to define relantionships.
Given the 2 classes below,
public class Person
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
public string Name{ get; set; }
}
public class Package
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
public Guid AccountId { get; set; }
public virtual Person Account { get; set; }
public Guid ShipperId { get; set; }
public virtual Client Shipper { get; set; }
[Required]
public Guid ReceiverId { get; set; }
public virtual Client Receiver { get; set; }
}
If I try to update the database, I get the error
Introducing FOREIGN KEY constraint 'FK_' on table 'Packages' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
On the other hand if I remove the property public Guid ....Id { get; set; }, the database is created with the foreign keys but the [Required] annotation as no effect.
What´s the difference between including a Guid property and not?
try to use this classes:
public class Person
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
public string Name{ get; set; }
[InverseProperty(nameof(Package.Account))]
public virtual ICollection<Package> Packages { get; set; }
}
public class Package
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
public Guid AccountId { get; set; }
[ForeignKey(nameof(AccountId))]
[InverseProperty("Packages")]
public virtual Person Account { get; set; }
}
and use this code in dbcontext:
modelBuilder.Entity<Package>(entity =>
{
entity.HasOne(d => d.Person)
.WithMany(p => p.Packages)
.HasForeignKey(d => d.AccountId)
.OnDelete(DeleteBehavior.ClientSetNull);
});

EF Migration fails due to GUID foreign key

I have the following models in my .NET Core 2.1 application:
public class Product
{
[Key]
public Guid ProductId { get; set; }
public virtual ICollection<Favourite> Favourites { get; set; }
}
public class Retailer
{
[Key]
public Guid BusinessId {get; set;}
public virtual ICollection<Favourite> Favourites { get; set; }
}
public class Favourite
{
[Key]
public Guid FavouriteId { get; set; }
[ForeignKey("Retailer_BusinessId")]
public virtual Retailer Business { get; set; }
[ForeignKey("Product_ProductId")]
public virtual Product Product { get; set; }
}
When trying to run an EF migration, I get the following error:
The relationship from 'Favourite.Business' to 'Retailer.Favourites'
with foreign key properties {'Retailer_BusinessId' : Nullable}
cannot target the primary key {'BusinessId' : Guid} because it is not
compatible. Configure a principal key or a set of compatible foreign
key properties for this relationship.
I suspect it's because I'm using Guid's as my keys in the foreign tables. How do I tell EF that?
It looks like EF expects the ForeignKey attribute to refer to the navigation property. I was able to reproduce the error you were getting and after making the following change, it migrated successfully.
public class Favourite
{
[Key]
public Guid FavouriteId { get; set; }
[ForeignKey("Business")]
public Guid BusinessId { get; set; }
[ForeignKey("Product")]
public Guid ProductId { get; set; }
public virtual Retailer Business { get; set; }
public virtual Product Product { get; set; }
}
EDIT: The way you were doing it was close, but you need to have the property and then specify just the property's name in the ForeignKey attribute.
public class Favourite
{
[Key]
public Guid FavouriteId { get; set; }
public Guid BusinessId { get; set; }
public Guid ProductId { get; set; }
[ForeignKey("BusinessId")]
public virtual Retailer Business { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
}

Fluent API one to one relationship mapping

I am trying to make a "One to one" association using the Fluent API. Here are my classes :
public class Person
{
public Guid Id { get; set; }
public Guid ProfilId { get; set; }
public DateTime InsertDate { get; set; }
public DateTime UpdateDate { get; set; }
public virtual Profil Profil { get; set; }
}
public class Profil
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
public String Email { get; set; }
public virtual Person Person { get; set; }
}
public class PersonMap : EntityTypeConfiguration<Person>
{
public PersonMap()
{
...
ToTable("Person");
HasRequired(t => t.Profil)
.WithOptional(c => c.Person)
.Map(m => m.MapKey("ProfilId"));
}
}
This implementation throws an exception Invalid column name 'ProfilId'.
Would somebody tell me how to set up a mapping with 1-1 relationship using these classes?
Thank you
When configuring one-to-one relationships,Entity Framework requires that the primary key of the dependent also be the foreign key, so you can map the relationship using Data Annotations as follow:
public class Person
{
[Key]
[ForeignKey("Profil")]
public Guid ProfilId { get; set; }
public DateTime InsertDate { get; set; }
public DateTime UpdateDate { get; set; }
public virtual Profil Profil { get; set; }
}
Or using Fluent Api:
HasKey(t=>t.ProfilId);
HasRequired(t => t.Profil).WithOptional(c => c.Person);
Edit 1:
Well, EF lets you create an one-to-one relationship between two entities with their own PKs, but you can't use a FK property, so, remove ProfileId in Person entity and configure the relationship this way:
HasRequired(t => t.Profil).WithOptional(c => c.Person);
The MapKey method is used to change the foreign key name in the database, but you can't have a property with the same name in your entity, otherwise, an exception will be thrown.

Mapping a foreign key with a different name

I have the following model:
public class Task
{
public int Id { get; set; }
public int UseraccountId { get; set; }
public virtual Useraccount Useraccount { get; set; }
}
The useraccountId is my foreign key showing to my useraccount entity/model.
The entity framework can map this foreign key to the virtual property because it removes the "Id", so "useraccountId" becomes "useraccount" -> mapping to "Useraccount".
What if I want to rename the foreign key "useraccountId" to "creatorId"? How can I now tell the Entity framework to map this foreign key to the virtual Useraccount property?
Use the ForeignKey attribute.
public class Task
{
public int Id { get; set; }
public int CreatorId { get; set; }
[ForeignKey("CreatorId")]
public virtual Useraccount Useraccount { get; set; }
}

Entity Framwork Mapping One-To-One Aspnet_Membership Table

I am using EF5 with the default aspnet_Membership Schema.
I have a custom User object with a foreign key referencing the aspnet_Membership table.
The foreign key in the User object is called 'AspnetID'
I need to map this one-to-one relationship with the fluent API but I am having no luck
Objects look like this:
public class aspnet_Membership
{
[Key]
public Guid UserId { get; set; }
public string Email { get; set; }
public DateTime CreateDate { get; set; }
public aspnet_Users aspnet_User { get; set; }
public User User { get; set; }
}
public class User
{
public int UserID { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
public Guid AspnetID { get; set; } //This is the foreign key referencing aspnet_Membership
public virtual aspnet_Membership Aspnet_Membership { get; set; }
}
I have tried this:
modelBuilder.Entity<User>().HasRequired(u => u.Aspnet_Membership).WithOptional(u => u.User);
But I know that I need to map the foreign key name some how...Any ideas?
You need to use WithRequiredPricipal() instead of WithOptional()
modelBuilder.Entity<User>()
.HasRequired(t => t.Aspnet_Membership)
.WithRequiredPrincipal(t => t.User);

Categories