如何添加父实体

时间:2016-03-05 00:48:45

标签: c# sql sql-server entity-framework

我的代码优先数据模型以标准ApplicationUser实体开始,其中包括邮政地址和结算属性。现在我通过添加父Account实体来扩展我的模型:

  • 一个帐户有很多ApplicationUsers; ApplicationUser现在具有相关帐户记录的不可为空的外键
  • 结算和邮寄地址现在与帐户实体而非ApplicationUser实体相关联,因此关联的属性已从ApplicationUser实体移至帐户实体

为了更新数据库模式以合并新的父表,我将每个现有的ApplicationUser分配给新创建的Account。所以,我需要为每个现有的ApplicationUser做两件事:

  1. 我需要创建一个新的帐户行,其帐单和邮政地址字段值取自ApplicationUser行。
  2. 我需要将ApplicationUser.AccountId外键字段设置为新创建的帐户行的主键值。
  3. 请注意,我的代码托管在Azure上,数据位于Azure SQL Server中。

    scaffolded Migration代码看起来像这样(大大简化)

    // Create the new Accounts table
    CreateTable(
        "dbo.Accounts",
        c => new
            {
                Id = c.Int(nullable: false, identity: true),
                BillingInfo = c.String(),
                PostalAddress = c.String(),
            })
        .PrimaryKey(t => t.Id);
    
    // Add the new FK column
    AddColumn("dbo.AspNetUsers", "AccountId", c => c.Int(nullable: false));
    CreateIndex("dbo.AspNetUsers", "AccountId");
    
    // Before we add the AspNetUsers.AccountId foreign key, we need to populate
    // the Accounts table (one Account for each User)
    Sql("some SQL command(s)")
    
    // Make the column a foreign key
    AddForeignKey("dbo.AspNetUsers", "AccountId", "dbo.Accounts", "Id", cascadeDelete: true);
    
    // Deleted fields
    DropColumn("dbo.AspNetUsers", "BillingInfo");
    DropColumn("dbo.AspNetUsers", "PostalAddress");
    

    据我所知,创建或修改数据的唯一选择是使用Sql()方法(或SqlFile()SqlResource()),如上面的代码所示。

    如果我只限于使用SQL,那么什么样的SQL命令才能完成任务?我可以在一个带有某种JOIN的大型命令(对于尚不存在的记录)中执行此操作,还是需要使用SQL循环(as shown in this article)?

1 个答案:

答案 0 :(得分:1)

核心理念非常简单:

  1. 您的架构和数据迁移应位于不同的迁移类

  2. 对于迁移,您需要在要插入的一侧引入临时伪FK列,并使用此列迁移数据。高层次的想法看起来大致如下:

  3. ALTER TABLE [dbo].[Accounts] ADD [_Temp_AspNetUserId] int;
    GO
    
    /*insert data into accounts with reference from AspNetUsers*/
    INSERT INTO [dbo].[Accounts] (BillingInfo, PostalAddress, _Temp_AspNetUserId)
    SELECT user.BillingInfo, user.PostalAddress, user.Id 
    FROM [dbo].[AspNetUsers] user
    
    /*update original foreign key relationship for [AspNetUsers] table*/
    UPDATE [dbo].[AspNetUsers]
    SET AccountId = [dbo].[AspNetUsers].Id
    FROM [dbo].[Accounts]
    WHERE [dbo].[Accounts]._Temp_AspNetUserId = [dbo].[AspNetUsers].Id 
    
    /*drop temporary column*/
    ALTER TABLE [dbo].[Accounts] DROP COLUMN [_Temp_AspNetUserId];
    GO
    

    很抱歉格式化,出于某些原因,如果我不添加评论标记,它看起来有点搞砸了。