Entity Framework getting confused about navigation property - c#

I'm using Entity Framework 6.1.1 and I have a Users table and a User_Documents table (1:many). I already had a navigation property from User_Documents to User were things were working fine.
public partial class User_Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long User_Document_ID { get; set; }
public long User_ID { get; set; }
[ForeignKey("User_ID")]
public virtual User User { get; set; }
}
I added a navigation property from Users to User_Documents
public partial class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long User_ID { get; set; }
[StringLength(50)]
public string Username { get; set; }
public virtual List<User_Document> Documents { get; set; }
}
and now I'm getting an error when I try to run the application:
System.Data.Entity.ModelConfiguration.ModelValidationException: One or
more validation errors were detected during model generation:
User_Documents: Name: Each member name in an EntityContainer must be
unique. A member with name 'User_Documents' is already defined.
Of course there is a table called User_Documents but no other property with that name. I'm not sure what's it getting confused by. Maybe it's taking the table name "User" and the property name "Documents" and trying to create something called "User_Documents" out of it? If I rename it to from Documents
to Some_Documents like this
public virtual List<User_Document> Some_Documents { get; set; }
then I get a different error stating
System.InvalidOperationException: The model backing the
'PipeTrackerContext' context has changed since the database was
created. Consider using Code First Migrations to update the database
So I run Add-Migration and I get this:
public override void Up()
{
AddColumn("dbo.User_Documents", "User_User_ID", c => c.Long());
CreateIndex("dbo.User_Documents", "User_User_ID");
AddForeignKey("dbo.User_Documents", "User_User_ID", "dbo.Users", "User_ID");
}
Why is it trying to add a new column called User_User_ID? Why can't I just add the Document navigation property like I want?

use InverseProperty Like this :
public partial class User_Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long User_Document_ID { get; set; }
public long User_ID { get; set; }
[ForeignKey("User_ID")]
[InverseProperty("Documents")]
public virtual User User { get; set; }
}
And :
public partial class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long User_ID { get; set; }
[StringLength(50)]
public string Username { get; set; }
[InverseProperty("User")]
public virtual List<User_Document> Documents { get; set; }
}

Why is it trying to add a new column called User_User_ID? Why can't I
just add the Document navigation property like I want?
By convention, it will create the foreign key as tablename_columnName which is User_User_ID. This happens when you remove the [ForeignKey("User_ID")] attribute OR don't have foreign key property.
If you change the property name Documents to something else (likeUserDocuments) you wont face this conflict of names.

Related

All containing foreign keys must be removed or redefined before the property can be removed - EF Core

I am getting the above error when trying to add migration after add a foreign key using Entity Framework core.
I am adding FK in
public class ApplicantDetail
{
[Key]
public int Id { get; set; }
[ForeignKey("GrantProgramFK")]
public GrantProgram GrantProgramId { get; set; }
--------
}
This FK ties to class
public class GrantProgram
{
[Key]
public int Id { get; set; }
-----
}
Any help is appreciated. I tried to remove the entity and run migration again, but failed.
Full error:
The property 'GrantProgramId' cannot be removed from entity type 'EFDataAccessLibrary.Models.ApplicantDetail' because it is being used in the foreign key {'GrantProgramId'} on 'EFDataAccessLibrary.Models.ApplicantDetail'. All containing foreign keys must be removed or redefined before the property can be removed
I found a page,
click here, but what does that mean? how to resolve it.
I had the same problem. I solved it by removing the "id" in the foreign key:
public class ApplicantDetail
{
[Key]
public int Id { get; set; }
[ForeignKey("GrantProgramFK")]
public GrantProgram GrantProgram { get; set; }
--------
}
I still don't know why. If anybody can explain, or give a solution to leave "id" in it, don't hesitate to tell us.
Since entityframework auomatically uses any identifoer ending with 'ID or Id or id', ensure no other property name ends with 'ID or Id or id'
I'd recommend to delete previous migrations file in the solution, this works for me
I was getting the same error, in my case all I did was undo the changes in AppDbContextModelSnapshot file (you can also delete the file) which is created in the migrations folder.
Turns out I had made an error before performing the migration, after which a model snapshot of my AppDbContext was created. After fixing the error, I tried the migration again, but the AppDbContextModelSnapshot was already modified, EF was not allowing to override with the same key of the same model (in this case GrantProgramFK from GrantProgram model) . So just undo the changes in your AppDbContextModelSnapshot file and perform the migration again.
I was able to solve the issue by going into ModelSnapShot.cs in the Migrations folder and making sure to delete all references to the property causing issues. You'll be looking for any references to 'GrantProgramIdId'.
Make sure to delete any lines where the snapshot creates foreign keys.
Change any instance where the property name includes the incorrect property name above.
Make sure you check the entire file. There should be two separate places where issues exist.
Also, delete any migrations where this property was included, then create a new migration and should be good to go.
I had a same issue. You have to delete(remove migration did not work either so I deleted manually) the migration and snapshot and change this field:
public GrantProgram GrantProgramId { get; set; }
to
public int GrantProgramId { get; set; }
You have to fix your classes before migration:
public class ApplicantDetail
{
[Key]
public int Id { get; set; }
public int? GrantProgramId { get; set; }
[ForeignKey("GrantProgramId")]
[InverseProperty("ApplicantDetails")]
public GrantProgram GrantProgram{ get; set; }
--------
}
public class GrantProgram
{
[Key]
public int Id { get; set; }
[InverseProperty(nameof(ApplicantDetail.GrantProram))]
public virtual ICollection<ApplicantDetail> ApplicantDetails{ get; set; }
-----
}
Add data annotations and everything will work smooth, see
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Address
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name ="Address Id")]
public int AddressId { get; set; }
public string Street { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
public int? StateId { get; set; }
public string Country { get; set; } = string.Empty;
public string ZipCode { get; set; } = string.Empty;
}
public class State
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name ="State Id")]
public int StateId { get; set; }
public string StateName { get; set; } = string.Empty;
}

EF6 Multiple foreign keys for ApplicationUser Error

I'm pretty new to Entity Framework and the code first approach and I'm stuck. Sorry if it's a dumb question.
I found some questions around here that look the same, but I get an other error then the ones other people get and I would love to solve it without the need to add other parameters if possible.
So Basically, I have my ApplicationUser(load in from Identity) that looks like this:
public class ApplicationUser : IdentityUser
{
public virtual Province Provincie { get; set; }
[ForeignKey("From")]
public virtual ICollection<Message> SentMessages { get; set; }
[ForeignKey("To")]
public virtual ICollection<Message> ReceivedMessages { get; set; }
}
And I have a Message Class that looks like:
public class Message
{
[Key]
public int ID { get; set; }
public virtual ApplicationUser From { get; set; }
public virtual ApplicationUser To { get; set; }
public String MessageContent { get; set; }
public DateTime Date { get; set; }
}
Now, when I try to add a migration i get the following error:
The ForeignKeyAttribute on property 'ReceivedMessages' on type 'EF_CF_Basics.Models.ApplicationUser' is not valid. The foreign key name 'To' was not found on the dependent type 'EF_CF_Basics.Models.Message'. The Name value should be a comma separated list of foreign key property names.
So actually, visual studio tells me it can't find the To in Message, but it is really there.
You probably want to use [InverseProperty("From")] instead of [ForeignKey("From")] and [InverseProperty("To")] instead of [ForeignKey("To")]. Foreign key properties must be scalars (int, string, Guid, etc.) but your From and To properties are actually entities, i.e. they are navigation properties.

Unable to determine the principal end of an association - Entity Framework Model First

I have created Entity Data Model in Visual Studio. Now I have file with SQL queries and C# classes generated from Model.
Question:
Classes are generated without annotations or code behind (Fluent API). Is it OK? I tried to run my application but exception was thrown:
Unable to determine the principal end of an association between the types 'Runnection.Models.Address' and 'Runnection.Models.User'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
I read that I can not use Fluent API with "Model First". So what can I do?
Code:
User
public partial class User
{
public User()
{
this.Events = new HashSet<Event>();
this.CreatedEvents = new HashSet<Event>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Photo { get; set; }
public int EventId { get; set; }
public string Nickname { get; set; }
public OwnerType OwnerType { get; set; }
public NetworkPlaceType PlaceType { get; set; }
public virtual ICollection<Event> Events { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<Event> CreatedEvents { get; set; }
public virtual Owner Owner { get; set; }
}
Address
public partial class Address
{
public int Id { get; set; }
public string Street { get; set; }
public string StreetNumber { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
public virtual User User { get; set; }
}
Context
//Model First does not use this method
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Address>().HasRequired(address => address.User)
.WithRequiredDependent();
modelBuilder.Entity<User>().HasRequired(user => user.Address)
.WithRequiredPrincipal();
base.OnModelCreating(modelBuilder);
}
You have to specify the principal in a one-to-one relationship.
public partial class Address
{
[Key, ForeignKey("User")]
public int Id { get; set; }
public string Street { get; set; }
public string StreetNumber { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
public virtual User User { get; set; }
}
By specifying a FK constraint, EF knows the User must exists first (the principal) and the Address follows.
Further reading at MSDN.
Also, see this SO answer.
Updated from comments
In the designer, select the association (line between Users & Address). On the properties window, hit the button with the [...] on Referential Constraint (or double click the line). Set the Principal as User.
Error:
Had same error of "Unable to determine the principal end of an association between the types 'Providence.Common.Data.Batch' and 'Providence.Common.Data.Batch'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.".
HOWEVER, note that this is the SAME table.
Cause: My database was MS SQL Server. Unfortunately when MS SQL Server's Management Studio adds foreign keys, it adds the default foreign key as Batch ID column of Batch table linking back to itself. You as developer are suppose to pick another table and id to truly foreign key to, but if you fail to it will still allow entry of the self referencing FK.
Solution:
Solution was to delete the default FK.
Cause 2: Another situation is that the current table may be fixed but the old historical image of the table when the EF's edmx was done had the default FK.
Solution 2: is to delete the table from the Model Browser's Entity Types list and click "yes" and then "Update Model from the Database" again.

How to allow null values on Foreign keys using EF?

How to allow null values on Foreign keys using EF?
public class User
{
public User()
{
}
public int idUser; { get; set; }
[Required]
public string UserName { get; set; }
public virtual Computer Computer{ get; set; }
}
public class Computer
{
public Computer()
{
}
[Key, ForeignKey("User")]
public int idUser{ get; set; }
public string ComputerName {get;set;}
public virtual User User { get; set; }
}
Running this I'm getting not null on the foreign key.
I assume you are using code first. If that is the case then you override OnModelCreating in the context class and add the following line
modelBuilder.Entity<Computer>().HasOptional(c => c.User);
================
Ok, you changed your post after I posted my answer.
You can use
int? idUser
for your user ID, this will let EF know that you are allowing a nullable relationship.
You can make use of ? keyword. It makes your type a Nullable type.
For example int doesn't allow nulls normally.
But after appending a ? to int you can assign null to it.
int? iCanHaveNull = null;
Late answer, I know, but it is an important topic.
You are trying to setup navigation properties. If you declare it correctly (as shown in the example below), then:
The property Computer contained in the User class is referring to ("points to") a computer by using foreign key idComputer.
Likewise, the property User contained in the Computer class is referring to ("points to") a User by using a foreign key idUser.
EF introduces this foreign key automatically if
You decorate the primary key Id of each entity with a [Key] attribute. A primary key must not be nullable per definition.
You declare the navigation property correctly (e.g. public virtual Computer Computer { get; set; } - which creates by convention a foreign key explicitly named via the ForeignKey attribute as idComputer). This foreign key is per definition nullable, unless you add the [Required] attribute to the navigation property. For example, if you want to make the foreign key in the User entity referring to ("pointing to") Computer mandatory, the declaration [Key, ForeignKey("idComputer"), Required] would do that.
Special Note for EF Core: You have to create a migration in the package manager console via
dotnet ef migrations add CreateMyDatabase
And then apply it to the database via:
dotnet ef database update --context myDbContext --project myProject
(replace CreateMyDatabase, myDbContext and myProjects by names of your choice - but myDbContext and myProjects must exist in your solution).
This is using toolset 5.0.3, you might need to upgrade it via
dotnet tool update --global dotnet-ef --version 5.0.3
Example:
// using System.ComponentModel.DataAnnotations;
// using System.ComponentModel.DataAnnotations.Schema;
public class User
{
public User() {}
[Key]
public int Id { get; set; }
[Required]
public string UserName { get; set; }
[Key, ForeignKey("idComputer")]
public virtual Computer Computer { get; set; }
}
public class Computer
{
public Computer() {}
[Key]
public int Id { get; set; }
[Required]
public string ComputerName { get; set; }
[Key, ForeignKey("idUser")]
public virtual User User { get; set; }
}
It might look weird to have something like public virtual User User { get; set} but this is a convention telling EF it is a navigation property, and all that is created in the database table is a foreign key (here: idUser in table Computer).
You can find a good description with some additional information here:
https://www.tektutorialshub.com/entity-framework-core/ef-core-relationships-navigation-properties/
How to allow null values on Foreign keys using EF?
Your database table should allow nulls as well if you are planning to take the following approach:
change
public int idUser; { get; set; }
[Required]
public string UserName { get; set; }
public virtual Computer Computer { get; set; }
To
public int idUser; { get; set; }
[Required]
public string UserName { get; set; }
public virtual Computer Computer{ get; set; }
And change
[Key, ForeignKey("User")]
public int idUser { get; set; }
public string ComputerName { get; set; }
public virtual User User { get; set; }
To
[Key, ForeignKey("User")]
public int? idUser { get; set; }
public string ComputerName { get; set; }
public virtual User User { get; set; }
The ? character, makes a field nullable. Make sure it is nullable in your database as well.

Entity Framework 5 not loading property

I'm working on a EF5 code-first database and it is giving me a lot of trouble on a foreign key. Also sorry if this is already answered somewhere else but I looked at countless of questions on here already and none helped so far.
I have this user class
public class User
{
[Key()]
[HiddenInput(DisplayValue=false)]
public int UserId { get; set; }
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[ScaffoldColumn(false)]
public CustomClass Custom { get; set; }
}
And this custom class
public class CustomClass
{
[Key()]
[HiddenInput(DisplayValue = false)]
public int CustomClassId { get; set; }
[Required]
public string Name { get; set; }
}
And this DataContext
public class SilkDbContext3 : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<CustomClass> CustomClasses { get; set; }
}
Now, the problem is I can save a PoseAnimation perfectly through the controller. I can also post and update an user with the basic properties (Username, Password), but when I add a custom class to the user, it saves it as a foreign key in the database row, but when I want to retrieve the user, the dbcontext just gives me back null for the custom class (whether I'm retrieving through GET or intellisense). Can anyone help me out here?
You'll need to either explicitly or eagerly load the related data, or mark the Custom property as virtual if you're using lazy loading.

Categories

Resources