8

我想知道是否有人遇到过类似的挑战:

我有一个数据库,其中包含一些从 Excel 文件中经过 ETL 处理(导入和转换)的数据。在我的 ASP.NET MVC Web 应用程序中,我使用 Code First 方法并在每次数据库更改时删除/创建:

#if DEBUG
  Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyDataContext>());
#endif

但是,由于数据库中的数据丢失了,我不得不再次进行 ETL,这很烦人。

由于数据库只会在模型更改时被删除,所以无论如何我都必须调整我的 ETL,我知道。但我宁愿更改我的数据库种子代码。

假设模型和 SQL 表都是最新的,有谁知道如何获取数据库的内容并生成种子代码?

编辑 1: 我打算使用自动生成的 Configuration.cs 及其种子方法,然后使用AddOrUpdate()方法将数据添加到数据库中:这是Microsoft 的迁移教程(特别是“设置种子方法”部分)。

4

2 回答 2

12

假设我们有一个简单的数据库表,其中包含3750条记录;

| Id   | Age | FullName        |
|------|-----|-----------------|
| 1    | 50  | Michael Jackson |
| 2    | 42  | Elvis Presley   |
| 3    | 48  | Whitney Houston |
| ...  | ... | ...             |
| 3750 | 57  | Prince          |

我们想使用自动生成的Configuration.cs文件及其Seed()方法在我们的数据库中创建这个表。

protected override void Seed(OurDbContainer context)
{
    context.GreatestSingers.AddOrUpdate(
            p => p.Id,
            new GreatestSinger { Id = 1, Age = 50, FullName = "Michael Jackson" },
            new GreatestSinger { Id = 2, Age = 42, FullName = "Elvis Presley" },
            new GreatestSinger { Id = 3, Age = 48, FullName = "Whitney Houston" }
            );
}

这是你应该做的。3750次!

但是您在现有的数据库表中已经有了这些数据。所以我们可以使用这些现有数据来创建Seed()代码。

在SQL 字符串连接的帮助下;

SELECT
CONCAT('new GreatestSinger { Id = ', Id ,', Age = ', Age ,', FullName = "', FullName ,'" },') 
FROM GreatestSinger

将为我们提供创建3750行数据所需的所有代码。

只需将其复制/粘贴到Seed()方法中即可。并从包管理器控制台

Add-Migration SeedDBwithSingersData

Update-Database
于 2016-08-17T16:23:22.330 回答
8

另一种播种数据的方法是在 Up 迁移中将其作为 sql 运行。

我有代码可以读取一个 sql 文件并运行它

using System;
using System.Data.Entity.Migrations;
using System.IO;

public partial class InsertStandingData : DbMigration
{
    public override void Up()
    {
        var baseDir = AppDomain.CurrentDomain
                               .BaseDirectory
                               .Replace("\\bin", string.Empty) + "\\Data\\Sql Scripts";

        Sql(File.ReadAllText(baseDir + "\\StandingData.sql"));
    }

    public override void Down()
    {
        //Add delete sql here
    }
}

因此,如果您的 ETL 为您生成 sql,那么您可以使用该技术。

在 Up 方法中这样做的优点是

  1. 它会比使用它更快,AddOrUpdate因为 AddOrUpdate每次调用它时都会查询数据库以获取任何已经存在的实体。
  2. 您通常从已知状态(例如空表)开始,因此您可能不需要检查数据是否已经存在。注意要确保这一点,您应该删除该Down方法中的数据,以便您可以一直撕下并再次备份。
  3. Up 方法不会在应用程序每次启动时运行。

Seed 方法提供了便利 - 它的优势(!?)每次应用程序启动时都会运行

但是,如果您更喜欢从那里运行 sql,请使用ExecuteSqlCommand而不是Sql

string baseDir = AppDomain.CurrentDomain.BaseDirectory.Replace("\\bin", string.Empty) 
              + "\\Data\\Sql Scripts";
string path = Path.Combine(baseDir, "StandingData");
foreach (string file in Directory.GetFiles(path, "*.sql"))
{
    context.Database.ExecuteSqlCommand(File.ReadAllText(file));
}

参考:

增量播种数据的最佳方法

准备数据库部署

数据库初始化程序和迁移种子方法

于 2013-10-09T09:23:10.337 回答