使用Code First迁移添加外键 [英] adding a foreign key with Code First migration

查看:196
本文介绍了使用Code First迁移添加外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



这是我在添加迁移之前的类

  public class Product b $ b {
public Product(){}
$ b public int ProductId {get;组; }
public string Name {get;组; }
public decimal Price {get;组; }
public bool Istaxable {get;组; }
public string DefaultImage {get;组; }
public IList< Feature>特点{get;组; }
public IList< Descriptor>描述符{get;组; }
public IList< Image>图片{get;组; }
public IList< Category>分类{get;组; }
}


public class Feature
{
public int Id {get;组; }
public string Title {get;组; }
public string描述{get;组; }




现在我想在我的特性中添加一个外键类和重构类:

  public class Product 
{
public Product(){}

public int ProductId {get;组; }
public string Name {get;组; }
public decimal Price {get;组; }
public bool Istaxable {get;组; }
public string DefaultImage {get;组; }
public IList< Feature>特点{get;组; }
public IList< Descriptor>描述符{get;组; }
public IList< Image>图片{get;组; }
public IList< Category>分类{get;组; }
}

public class Feature
{
public int Id {get;组; }
public string Title {get;组; }
public string描述{get;组; }
public string Image {get;组; }
公共字符串VideoLink {get;组; }

public int ProductId {get;组; }
public Product Product {get;组; }



$我添加了一个迁移 Add-Migration 命令。
我添加了一个 Update-Database 命令,这里是我回来的:

lockquote

ALTER TABLE语句与FOREIGN KEY约束
FK_dbo.ProductFeatures_dbo.Products_ProductId冲突。数据库CBL,表dbo.Products,ProductId列中发生冲突

做解决这个问题,并让我的迁移恢复正常?
解决方案

解决这个问题的关键是打破你的迁移到两次迁移。首先,添加一个可为空的字段并填写数据。第二,使该字段成为必需的外键。



第一迁移




  1. 将这个新的属性作为一个可为空的类型(例如int?)添加到你的类中。
    $ b $ pre $ public $ MyOtherEntity
    {
    public int Id {get;组; }
    }

    public class MyEntity
    {
    ...
    //对MyOtherEntity的新引用
    public int? MyOtherEntityId {get;组; }
    ...
    }


  2. 创建迁移。注意:迁移名称并不重要,但是像AddBlogPosts1这样的内容可以很容易阅读。

     > add-migration AddMyEntityMyOtherEntity1 


  3. 这应该支持如下的迁移:

      public partial class AddMyTableNewProperty1:DbMigration 
    {
    public override void Up()
    {
    AddColumn(dbo.MyEntity,MyOtherEntityId,c => c.Int());

    public override void Down()
    {
    DropColumn(dbo.MyEntity,MyOtherEntityId);




    $现在手动编辑生成的迁移以添加新字段的默认值。最简单的情况是默认值是不变的。如果需要,您可以在SQL中添加更多的逻辑。这个例子假设所有的MyEntity实例指向ID为1的MyOtherEntity实例。
    $ b $ pre $ b {
    public override void Up()
    {
    AddColumn(dbo.MyEntity,MyOtherEntityId,c => c.Int());

    //把这个加到
    Sql(@UPDATE dbo.MyEntity SET MyOtherEntityId = 1
    where MyOtherEntity IS NULL);

    public override void Down()
    {
    DropColumn(dbo.MyEntity,MyOtherEntityId);




    $ li $更新数据库

     > update-database 




  4. 第二迁移


    $ b


    1. 返回MyEntity类并更改新属性以表示强制外键。

        public class MyEntity 
      {
      ...
      //更改int?为了使它强制
      public int MyOtherEntityId {get;组; }

      //创建对其他实体的引用
      public virtual MyOtherEntity MyOtherEntity {get;组; }
      ...
      }


    2. p>

       > add-migration AddMyEntityMyOtherEntity2 


    3. 这应该创建如下的迁移: b
      $ b

        public partial class AddMyEntityMyOtherEntity2:DbMigration 
      {
      public override void Up()
      {
      AlterColumn (dbo.MyEntity,MyOtherEntityId,c => c.Int(nullable:false));
      CreateIndex(dbo.MyEntity,MyOtherEntityId);
      AddForeignKey(dbo.MyEntity,MyOtherEntityId,dbo.MyOtherEntity,Id);

      public override void Down()
      {
      DropForeignKey(dbo.MyEntity,MyOtherEntityId,dbo.MyOtherEntity);
      DropIndex(dbo.MyEntity,new [] {MyOtherEntityId});
      AlterColumn(dbo.MyEntity,MyOtherEntityId,c => c.Int());




      $ li $更新数据库

       > update-database 




    其他注意事项




    1. 此技术适用于在应用程序启动时应用的迁移。
    2. 添加更复杂的映射SQL是可能的,但这里没有说明。


    I have an error when trying to update my database after adding a migration.

    Here are my classes before add-migration

    public class Product
    {
        public Product() { }
    
        public int ProductId { get; set; } 
        public string Name { get; set; }
        public decimal Price { get; set; }
        public bool Istaxable { get; set; }
        public string DefaultImage { get; set; }
        public IList<Feature> Features { get; set; }
        public IList<Descriptor> Descriptors { get; set; }
        public IList<Image> Images { get; set; }
        public IList<Category> Categories { get; set; }
    }
    
    
    public class Feature
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
    
    }
    

    Now I wanted to add a foreign key in my Feature class and refactored the classes this way:

    public class Product
    {
        public Product() { }
    
        public int ProductId { get; set; } 
        public string Name { get; set; }
        public decimal Price { get; set; }
        public bool Istaxable { get; set; }
        public string DefaultImage { get; set; }
        public IList<Feature> Features { get; set; }
        public IList<Descriptor> Descriptors { get; set; }
        public IList<Image> Images { get; set; }
        public IList<Category> Categories { get; set; }
    }
    
    public class Feature
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public string Image { get; set; }
        public string VideoLink { get; set; }
    
        public int ProductId { get; set; }
        public Product Product { get; set; }
    }
    

    I added a migration with Add-Migration command. I added an Update-Database command and here is what I got back:

    The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.ProductFeatures_dbo.Products_ProductId". The conflict occurred in database "CBL", table "dbo.Products", column 'ProductId'

    What can I do to solve this problem and get my migrations back to normal?

    解决方案

    The key to solving this problem is to break your migration into two migrations. First, add a nullable field and fill in the data. Second, make the field a required foreign key.

    First Migration

    1. Add the new property to your class as a nullable type (e.g. int?)

      public class MyOtherEntity
      {
          public int Id { get; set; }
      }
      
      public class MyEntity
      {
          ...
          // New reference to MyOtherEntity
          public int? MyOtherEntityId { get; set; }
          ...
      }
      

    2. Create a migration. NOTE: Migration name is not important, but something like "AddBlogPosts1" makes it easy to read.

      > add-migration AddMyEntityMyOtherEntity1
      

    3. This should scaffold a migration that looks like this:

      public partial class AddMyTableNewProperty1 : DbMigration
      {
          public override void Up()
          {
              AddColumn("dbo.MyEntity", "MyOtherEntityId", c => c.Int());
          }
          public override void Down()
          {
              DropColumn("dbo.MyEntity", "MyOtherEntityId");
          }
      }
      

    4. Now manually edit the generated migration to add a default value for the new field. The easiest case is when the default value is invariant. You can add more logic in the SQL if needed. This example assumed all the MyEntity instances point to the same MyOtherEntity instance with ID 1.

      public partial class AddMyTableNewProperty1 : DbMigration
      {
          public override void Up()
          {
              AddColumn("dbo.MyEntity", "MyOtherEntityId", c => c.Int());
      
              // ADD THIS BY HAND
              Sql(@"UPDATE dbo.MyEntity SET MyOtherEntityId = 1
                    where MyOtherEntity IS NULL");
          }
          public override void Down()
          {
              DropColumn("dbo.MyEntity", "MyOtherEntityId");
          }
      }
      

    5. Update the database

      > update-database
      

    Second Migration

    1. Go back to your MyEntity class and change the new property to represent a mandatory foreign key.

      public class MyEntity
      {
          ...
          // Change the int? to int to make it mandatory
          public int MyOtherEntityId { get; set; }
      
          // Create a reference to the other entity
          public virtual MyOtherEntity MyOtherEntity { get; set; }
          ...
      }
      

    2. Create another migration

      > add-migration AddMyEntityMyOtherEntity2
      

    3. This should create a migration like the following:

      public partial class AddMyEntityMyOtherEntity2: DbMigration
      {
          public override void Up()
          {
              AlterColumn("dbo.MyEntity", "MyOtherEntityId", c => c.Int(nullable: false));
              CreateIndex("dbo.MyEntity", "MyOtherEntityId");
              AddForeignKey("dbo.MyEntity", "MyOtherEntityId", "dbo.MyOtherEntity", "Id");
          }
          public override void Down()
          {
              DropForeignKey("dbo.MyEntity", "MyOtherEntityId", "dbo.MyOtherEntity");
              DropIndex("dbo.MyEntity", new[] { "MyOtherEntityId" });
              AlterColumn("dbo.MyEntity", "MyOtherEntityId", c => c.Int());
          }
      }
      

    4. Update the database

      > update-database
      

    Other Notes

    1. This technique works for migrations applied during application start up.
    2. Adding more complex mappings for the new column in the SQL are possible, but not illustrated here.

    这篇关于使用Code First迁移添加外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆