I have an inherited Code First Entity Framework project where the entities in C# have fallen out of phase with the database. When I attempt to create a parent-to-child 1-to-1 relationship with an existing table, EF is unable to create valid SQL for establishing the foreign key (FK) relationship.
In this case, the parent entity is called ApplicantRegistration
. I need to relate this, one-to-one, with the User
entity to represent a CaseManager
that belongs to each applicant. (The User
entity is used as a child relation in many more parent entities.)
Simple enough on its face. I added the following to the ApplicantRegistration
...
public User CaseManager { get; set; }
But the User
has an id that says this...
public class User
{
[Key]
public int UserId { get; set; }
// ...
... and, in MySQL, the Users
table related to that entity has this...
`UserId` bigint(15) NOT NULL AUTO_INCREMENT,
>>> Since bigint
and int
don't jibe, I get an error when EF tries to create a Foreign Key. <<<
The int column (EF names it CaseManager_UserId
) gets added to the ApplicantRegistrations
table fine, but the FK creation borks.
Here's the autogenerated EF SQL:
ALTER TABLE ApplicantRegistrations
ADD COLUMN CaseManager_UserId int NULL
CREATE INDEX IX_ApplicantRegistrations_CaseManager_UserId ON ApplicantRegistrations (CaseManager_UserId)
ALTER TABLE ApplicantRegistrations
ADD CONSTRAINT FK_ApplicantRegistrations_Users_CaseManager_UserId FOREIGN KEY (CaseManager_UserId) REFERENCES Users (UserId)
ON DELETE NO ACTION ON UPDATE NO ACTION
ADD CONSTRAINT FK_ApplicantRegistrations_Users_CaseManager_UserId FOREIGN KEY (CaseManager_UserId)
isn't going to work, because int
and bigint
don't match.
Options Considered
1. Swap int
to long
in User
in the C#
I originally started swapping from int
for UserId
on the User
entity over to long
(this is in C#) to see if that'd match up with bigint
in EF's generated code, but that quickly became a mess, practically speaking. After I swapped public int UserId { get; set; }
over to public long UserId { get; set; }
and fixed the fallout from changing type on related entities & code, I received a number of errors like the following when trying to Add-Migration
:
System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:
ProgramWorksite_WorksiteAdministratorUser_Target_ProgramWorksite_WorksiteAdministratorUser_Source: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. The type of property 'WorksiteAdministratorUserId' on entity 'ProgramWorksite' does not match the type of property 'UserId' on entity 'User' in the referential constraint 'ProgramWorksite_WorksiteAdministratorUser'.
That makes sense, of course -- now I've got to change all the other places User
is used as a child relation. (There are 33 of them, and it occurs to me there should be an easier way, so I shelved int
to long
in User
for now in the hopes of finding something better, but I'll probably come back to this after posting.)
2. Swap bigint
for int
in Users
in MySQL
I also tried to swap from bigint
to int
in MySQL, but that would require dropping & replacing tons of FK relationships with UserId
in the database, which is a possible solution, but not much fun. I think fixing it in the C# would be easier -- assuming long
will map to bigint
, which I don't know for sure. (UPDATE: long
does map to bigint(15)
, at least in this system.)
3. Try annotating the column in ApplicantRegistration
I thought I might be able to use a Column
override for EF's purposes only like this inside of Applicant
...
Column("CaseManagerId", TypeName = "bigint(15)")]
public User CaseManager { get; set; }
Unfortunately, that gave the same error as before -- and it didn't use the CaseManagerId
name I'd used, instead defaulting back to CaseManager_UserId
. So, at best, I've done the annotation wrong.
The annotation route really is my favorite, if there's a way to make it work -- if it could make EF ignore what's in the User
entity's UserId
definition long enough to create the FK relationship and complete the migration, I'm golden.
What's the most efficient way to insert this new relationship if I don't want to drop EF Code First?