简体   繁体   中英

Require One of Multiple Foreign Keys in Entity Framework

I'm basically trying to enforce this in Entity Framework: Require Only One Of Multiple Columns Be Not Null

My database has several 1:m relationships where the child entity belongs to one of several parent entities. For example, let's say I have tables for Teachers , Students , and Guardians . Each of those can have many PhoneNumbers and EmailAddresses . I am using EF Code First, and my models look something like:

public class Teacher {
    public int Id { get; set; }
    public string Name { get; set; }
    public List<PhoneNumber> PhoneNumbers { get; set; }
    public List<EmailAddress> EmailAddresses { get; set; }
}

public class Student {
    public int Id { get; set; }
    public string Name { get; set; }
    public List<PhoneNumber> PhoneNumbers { get; set; }
    public List<EmailAddress> EmailAddresses { get; set; }
}

public class Guardian {
    public int Id { get; set; }
    public string Name { get; set; }
    public List<PhoneNumber> PhoneNumbers { get; set; }
    public List<EmailAddress> EmailAddresses { get; set; }
}

public class PhoneNumber {
    public int Id { get; set; }
    public string Number { get; set; }
}

public class EmailAddress {
    public int Id { get; set; }
    public string Email { get; set; }
}

When I run the migration, this creates the database with the tables/columns I would expect. The PhoneNumbers and EmailAddresses tables each have columns Teacher_Id , Student_Id , and Guardian_Id , which are foreign keys to their respective parent entity. However, there are no constraints on how many parent entities can be set on the child. For example, I can create a PhoneNumber that has all three parent IDs set to null, or I can set both a Teacher_Id and a Guardian_Id .

I tried adding a required attribute to the parents like so:

public class Teacher { // Also Student/Guardian
    public int Id { get; set; }
    public string Name { get; set; }

    [Required]
    public List<PhoneNumber> PhoneNumbers { get; set; }

    [Required]
    public List<EmailAddress> EmailAddresses { get; set; }
}

That does not seem to have any effect.

I think there is no way to do this on entities. Instead, create a migration and try to alter the table in migration class like this:

    public partial class YourMigrationName: Migration
                            {
                              protected override void Up(MigrationBuilder migrationBuilder)
                                {
                                    migrationBuilder.Sql("ALTER TABLE [dbo].[PhoneNumber]  
    WITH CHECK ADD CONSTRAINT [CK_PhoneNumer_Teacher_Student_Guardian] CHECK  (Teacher_Id
 is not null or Student_Id is not null or Guardian_Id is not null)
                            GO
                            ALTER TABLE [dbo].[EmailAddress]  WITH CHECK ADD  CONSTRAINT 
            [CK_EmailAddress_Teacher_Student_Guardian] CHECK  (Teacher_Id is not null or 
        Student_Id is not null or Guardian_Id is not null)
                        ");
                                }
                            }

Try this:

public class PhoneNumber 
{
    public int Id { get; set; }
    public string Number { get; set; }
    //Added this code:
    [Required] 
    public Teacher Teacher { get; set;}
}

public class EmailAddress {
    public int Id { get; set; }
    public string Email { get; set; }
    //Added this code:  
    [Required]
    public Teacher Teacher { get; set;}
}

That would make sure you cannot create PhoneNumber without Teacher. You can also do this:

public class PhoneNumber 
{
    public int Id { get; set; }
    public string Number { get; set; }
    public int TeacherId
    public Teacher Teacher { get; set;}
}

That would also detect that you want to add constraint on your PhoneNumber. Both ways work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM