Entity Framework - Code First - Foreign Key Constraint

1

I am developing a database using a code-first approach with entity framework.

I want to use foreign keys between a few tables, for instance:

 public class Producer
    {

        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(254)]
        public string Name { get; set; }
    }

then another files model is simplified as

 public class Product
    {

        [Key]
        public int Id { get; set; }

        [Required]
        [StringLength(254)]
        public string Name { get; set; }
    }

What i want is to define a ProducerId field on the Product and have it link to the Producers ID field, but i cant tell how to tell it what model/table its linking to.

Can anyone clarify? I think based on what ive read it may seem like i need to make the ID fields more descriptive and EF will find the field, is ProductId for the Products Id field - but im still not positive it will work across the tables.

Is that correct or have i missed something?

Edit:

I tried the first answer below, but using more tables than just the two, and got this error:


fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (46ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE `Product` (
          `ProductId` int NOT NULL AUTO_INCREMENT,
          `ProducerId` int NOT NULL,
          `ProductCategoryId` int NOT NULL,
          `ProductStyleId` int NOT NULL,
          `Name` varchar(254) NULL,
          `Year` datetime NOT NULL,
          `CreatedAt` datetime NOT NULL,
          `CategoryId` int NOT NULL,
          `StyleId` int NOT NULL,
          `Image` varbinary(4000) NULL,
          `TastingNotes` text NULL,
          `Description` text NULL,
          PRIMARY KEY (`ProductId`),
          CONSTRAINT `FK_Product_Producers_ProducerId` FOREIGN KEY (`ProducerId`) REFERENCES `Producers` (`ProducerId`) ON DELETE CASCADE,
          CONSTRAINT `FK_Product_ProductCategory_ProductCategoryId` FOREIGN KEY (`ProductCategoryId`) REFERENCES `ProductCategory` (`ProductCategoryId`) ON DELETE CASCADE,
          CONSTRAINT `FK_Product_ProductStyle_ProductStyleId` FOREIGN KEY (`ProductStyleId`) REFERENCES `ProductStyle` (`ProductStyleId`) ON DELETE CASCADE
      );
Failed executing DbCommand (46ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE `Product` (
    `ProductId` int NOT NULL AUTO_INCREMENT,
    `ProducerId` int NOT NULL,
    `ProductCategoryId` int NOT NULL,
    `ProductStyleId` int NOT NULL,
    `Name` varchar(254) NULL,
    `Year` datetime NOT NULL,
    `CreatedAt` datetime NOT NULL,
    `CategoryId` int NOT NULL,
    `StyleId` int NOT NULL,
    `Image` varbinary(4000) NULL,
    `TastingNotes` text NULL,
    `Description` text NULL,
    PRIMARY KEY (`ProductId`),
    CONSTRAINT `FK_Product_Producers_ProducerId` FOREIGN KEY (`ProducerId`) REFERENCES `Producers` (`ProducerId`) ON DELETE CASCADE,
    CONSTRAINT `FK_Product_ProductCategory_ProductCategoryId` FOREIGN KEY (`ProductCategoryId`) REFERENCES `ProductCategory` (`ProductCategoryId`) ON DELETE CASCADE,
    CONSTRAINT `FK_Product_ProductStyle_ProductStyleId` FOREIGN KEY (`ProductStyleId`) REFERENCES `ProductStyle` (`ProductStyleId`) ON DELETE CASCADE
);
MySql.Data.MySqlClient.MySqlException (0x80004005): Cannot add foreign key constraint
   at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
   at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
   at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
C
c#
asp.net
entity-framework
ef-code-first
asked on Stack Overflow Sep 18, 2020 by aescript • edited Sep 18, 2020 by aescript

2 Answers

1

I'd lay it out like so, assuming your producers have a one to many relationship with products:

public class Producer
    {

        [Key]
        public int ProducerID { get; set; }

        [Required]
        [StringLength(254)]
        public string Name { get; set; }

        public ICollection<Product> Products { get; set; }
    }

public class Product
    {

        [Key]
        public int ProductID { get; set; }

        public int ProducerID { get; set; }

        [Required]
        [StringLength(254)]
        public string Name { get; set; }

        public Producer Producer { get; set;}
    }

EF will do the heavy lifting during the migration from there and you can check the context model snapshot to ensure it looks right before updating your DB. I'd recommend checking out the EF tutorials in the Microsoft Docs if you haven't already.

answered on Stack Overflow Sep 18, 2020 by jtucker13
1

To add a foreign key just add this on the Product class add:

public int ProducerId { get; set; }

[ForeignKey("ProducerId")]  //This attribute is optional bc EF should recognize Product obj specifi

public virtual Producer Producer { get; set; }

By adding public virtual Producer Producer EF Core should recognize the ProducerId property as a foreign key. virtual is used to enable Lazy Loading if you like.

The [ForeignKey()] is an optional attribute to explicitly point to the foreign and navigation keys. This post should further explain the optional use of [ForeignKey()]. How Should I Declare Foreign Key Relationships Using Code First Entity Framework (4.1) in MVC3?

To be clear, to simply add a foreign key, all that is required is adding this to class:

public int ProducerId { get; set; }
public virtual Producer Producer { get; set; }
answered on Stack Overflow Sep 18, 2020 by janzen • edited Sep 18, 2020 by janzen

User contributions licensed under CC BY-SA 3.0