Code first driving me crazy with foreign key exception - c#

These are my model classes:
public class Organization
{
public Organization()
{
}
[DisplayName("Organization Id")]
public int OrganizationId { get; set; }
[StringLength(128)]
[DisplayName("Organization Name")]
public string Name { get; set; }
}
public class User
{
public User()
{
Roles = new List<Role>();
}
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid UserGuid { get; set; }
[StringLength(25)]
public string FirstName { get; set; }
[StringLength(25)]
public string LastName { get; set; }
public virtual List<Role> Roles { get; set; }
public int OrganizationId { get; set; }
[ForeignKey("OrganizationId")]
public virtual Organization Organization { get; set; }
}
This is my code:
Organization organization = new Organization { Name = "Test", };
context.Organizations.Add(organization);
And I get this:
The INSERT statement conflicted with the FOREIGN KEY constraint
\"Organization_Users\". The conflict occurred in database
\"SampleDB\", table \"dbo.Organizations\", column
'OrganizationId'.\r\nThe statement has been terminated.
Isn't this weird? I am just adding an organization. What problem can it possibly have in this?
P.S: My user table does have OrganizationId that is foreign key and pointing to Organization table. So far so good but why is the exception thrown? I am adding a master Organization record. How does that violate foreign key constraint?

I would expect the database id to be generated for the organisation as well:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[DisplayName("Organization Id")]
public int OrganizationId { get; set; }
Either that, or you need toset it to a valid, unique value yourself before saving
Alternative guess:
The name Organization_Users suggests that there is (or was) a relation from the Organization table to th Users (perhaps via a relation table). Did you show the full code? Code there be remnants of this old relationship in the database? It is not enough to remove such relations just from the C# code (because the datatabase will continue checking the constraints, until the unused fields/relations are dropped from the actual database schema).

It appears that EF has created the relationship in the wrong direction.
The User class should have an Organization not an OrganizationID.
The Organization class should have a list of users.

Related

SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Users_Companies_CompanyId"

I want to add a new user in my database but take the exception. Unfortunately I'm new to both SQL Server and EF, but searching for the answer made me understand that the problem is somewhere in the SQL Server tables and impossibility of connection user and company there. Should I do something with Id or CompanyId or what?
SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Users_Companies_CompanyId". The conflict occurred in database "companiesdb", table "dbo.Companies", column 'Id'. The statement has been terminated.
Code:
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public int CompanyId { get; set; } // for what???
public Company Company { get; set; }
public int Id { get; set; } //for what?
}
public class Company
{
public int Id { get; set; } //for what?
public string Name { get; set; }
public List<User> Users { get; set; }
public Company()
{
Users = new List<User>();
}
}
using Microsoft.EntityFrameworkCore;
namespace DataApp1.Models
{
public class UserDb : DbContext
{
public DbSet<User> Users { get; set; } //create db for users
public DbSet<Company> Companies { get; set; } //and for companies they belong
public UserDb(DbContextOptions<UserDb> options)
: base(options)
{
Database.EnsureCreated();
}
}
}
Your User class, which apparently relates to your Users table, has a field for CompanyId. Based on the error, your database requires a correct company ID to be added to the DB every time.
If you have not added the company to the Companies table before adding a User, the insert will fail with this error. If you insert the User with no value in the CompanyId field, this error will occur.
So, your correct program flow would be:
Add Company to Companies if it doesn't exist there
Get the correct CompanyId
Add the CompanyId to the CompanyId field in the User record before saving it.

Different user types with ASP.NET Core 1.1 Identity and Entity Framework Core

Using ASP.NET Core Identity with Entity framework Core i need to add different types of users in my app:
Let's say that i need two types of users: "Student" and "Teacher"; both of them are also ApplicationUsers since they have to be authenticated to access the app.
I have accomplish that creating two tables: one for Student and one for Teacher. Both tables are one-to-one related with the ApplicationUser table.
I'd like to know if this is correct or if i'm doing something wrong, because when updating the database with migrations it throws the error "FOREIGN KEY 'FK_Student_AspNetUsers_Id' in 'Student' table may cause cycles or multiple cascade paths. specify ON DELETE NO ACTION or UPDATE NO ACTION". And, in any case, if it goes right, at the end i'd have an ApplicationUser class with two columns (one for StudentId and another for TeacherId), and one of them will always be null since an ApplicationUser can be a Student or a Teacher, but not both.
Here is my code so far:
public class ApplicationUser : IdentityUser<int>
{
public string Name { get; set; }
[ForeignKey("Teacher")]
public int? TeacherId { get; set; }
public virtual Teacher Teacher { get; set; }
[ForeignKey("Student")]
public int? StudentId { get; set; }
public virtual Student Student { get; set; }
}
public class Student
{
[Key, ForeignKey("User")]
public int Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
public string MotherMaidenName { get; set; }
public DateTime BirthDate { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ApplicationUser User { get; set; }
}
public class Teacher
{
[Key,ForeignKey("User")]
public int Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
public string MotherMaidenNAme { get; set; }
public virtual ApplicationUser User { get; set; }
}
UPDATED: I've set TeacherId and StudentId as nullable, so the Error mentioned above is gone.
You shouldn't create different tables for each user type you have.
You should create roles and assign that roles to a user. For example create a role student and a role teacher and assign them acording to your needs.
So I would say what you've done isn't a good design.
When you need to save additional values for a student/teacher than I would do something similar to your design.
But I wouldn't add ID's for my student/teacher to my ApplicationUser class.
I would simply add a UserId to my student/teacher class.
So the design issue should be that you're trying to put that stuff into the ApplicationUser class.

Adding data with foreign key in database

This is my first time working with database so I'm still trying to understand how all this works.
I'm trying to write my data (User, Note, Group) to database. I have three classes.
First one is User:
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public List<Group> groups { get; set; }
public User()
{
this.groups = new List<Group>();
}
}
Note:
public class Note
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Title { get; set; }
public string Content{ get; set; }
public string Password { get; set; }
public List<Group> groups { get; set; }
}
And Group:
public class Group
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
}
I know I should add foreign key but I don't know where and how. I'm really stuck so any help would be greatly appreciated!
Before you add foreign key. First you must define the relationship cardinality between each tables. To define it, you can just imagine how each table are represented in real life.
For example, a group can/must contain more than one user. And a user can be inside a single group or more at once.
So we define the relationship between a group and a user as MANY TO MANY, unless, you define it so that one user may only be registered to one group. In which case the relationship would become ONE TO MANY. With ONE being the group table and MANY refers to the user table.
Now, once the relationship is defined, usually the foreign key is set in the MANY table, in this case, it's the user table. So every user would have a foreign key called "Group".
As for the MANY TO MANY relationship the foreign key is set in both table. So that each table contains the key of the other.

Entity Framework 6 CF: Remove One-to-Many

My classes are something like:
public class Contact
{
public string Name { get; set; }
public virtual ICollection<Person> Persons { get; set; }
[Key]
public int Id { get; set; }
}
public class Person
{
public string Name { get; set; }
public virtual Contact Contact { get; set; }
public int? ContactId { get; set; }
[Key]
public int Id { get; set; }
}
When I try to remove a Contact that has in it's collection a Person, I get this error:
The primary key value cannot be deleted because references to this key
still exist. [ Foreign key constraint name =
FK_dbo.Persons_dbo.Contacts_ContactsId ]
I set the ContactId to int? so it could be nullable, and the database says it's a nullable FK, and it works fine in general. Just when I try to delete the entity with the collection that I get this error.
I want to be able to delete a Contact, but not the Persons inside it, what should I do?
The default behaviour of EF is to null foreign keys when their principal relationship is deleted. However, no database rule will be setup. In order for EF to issue update statements on the foreign keys of the dependents, they will need to be loaded into the context.
So make sure when you delete Contact all it's dependent Person entities have been loaded.

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.

Categories

Resources