从ASP.NET MVC中的现有数据库生成种子代码

时间:2013-10-07 14:54:50

标签: sql asp.net-mvc-4 etl ef-migrations

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

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

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

但是,由于数据库中的数据丢失,我必须再次ETL,这很烦人。

因为,只有在模型更改时才会删除数据库,无论如何我都要调整我的ETL,我知道。但我宁愿改变我的数据库种子代码。

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

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

2 个答案:

答案 0 :(得分:7)

假设我们有一个简单的数据库表,其中包含 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 String Concatenation ;

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

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

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

Add-Migration SeedDBwithSingersData

Update-Database

答案 1 :(得分:5)

另一种播种数据的方法是在Up migration中将其作为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更快 Down每次调用数据库时都会查询数据库 已存在的实体。
  2. 你通常会从一个已知的状态(例如空表)开始 不需要检查数据是否已存在。请注意确保这一点 然后你应该删除ExecuteSqlCommand方法中的数据,以便你可以 一路向下撕裂,然后重新起来。
  3. 每次应用程序启动时都不会运行Up方法。
  4. Seed方法提供了方便性 - 每次应用程序启动时它都有优势(!?)

    但如果你想从那里运行sql,请使用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)); }

    {{1}}

    参考文献:

    Best way to incrementally seed data

    Preparing for database deployment

    Database Initializer and Migrations Seed Methods