实体框架-代码优先-外键约束

问题描述

我正在使用代码优先方法和实体框架来开发数据库。

我想在一些表之间使用外键,例如:

 public class Producer
    {

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

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

然后将另一个文件模型简化为

 public class Product
    {

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

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

我想要的是在产品上定义一个ProducerId字段,并将其链接到Producers ID字段,但是我不能告诉如何告诉它链接到哪个模型/表。

任何人都可以澄清吗?我认为,根据我所读的内容,我似乎需要使ID字段更具描述性,并且EF会找到该字段,该字段是Products Id字段的ProductId-但我仍然不肯定,它将可以在所有表​​格中使用。

是正确的还是我错过了什么?

编辑:

我尝试了下面的第一个答案,但是使用的表比两个表更多,并且出现此错误:


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=[],CommandTimeout='30']
CREATE TABLE `Product` (
    `ProductId` int NOT NULL AUTO_INCREMENT,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

解决方法

假设您的生产者与产品具有一对多的关系,我会这样安排:

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将在从那里进行迁移期间进行繁重的工作,您可以在更新数据库之前检查上下文模型快照,以确保它看起来正确。如果您还没有的话,建议您查看Microsoft Docs中的EF教程。

,

要添加foreign key,只需在Product类中添加即可:

public int ProducerId { get; set; }

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

public virtual Producer Producer { get; set; }

通过添加public virtual Producer Producer,EF Core应该将ProducerId属性识别为foreign keyvirtual用于启用Lazy Loading

[ForeignKey()]是一个可选属性,用于显式指向foreignnavigation键。这篇文章应该进一步说明[ForeignKey()]的可选用法。 How Should I Declare Foreign Key Relationships Using Code First Entity Framework (4.1) in MVC3?

要清楚,只需添加一个foreign键,只需将其添加到类中即可。

public int ProducerId { get; set; }
public virtual Producer Producer { get; set; }

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...