我想知道是否有人遇到过类似的挑战:
我有一个数据库,其中包含一些从Excel文件ETL(导入和转换(的数据。在我的 ASP.NET MVC Web 应用程序中,我使用代码优先方法并在每次数据库更改时删除/创建:
#if DEBUG
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyDataContext>());
#endif
但是,由于数据库中的数据丢失了,我必须再次对其进行 ETL,这很烦人。
由于数据库只会在模型更改时被删除,因此无论如何我都必须调整我的 ETL,我知道这一点。但我宁愿更改我的数据库种子代码。
有谁知道如何获取数据库的内容并生成种子代码,假设模型和SQL表都是最新的?
编辑 1:我计划使用自动生成的 Configuration.cs 及其 Seed 方法,然后使用AddOrUpdate()
方法将数据添加到数据库中: 这是Microsoft关于迁移的教程(特别是"设置 Seed 方法"部分(。
假设我们有一个简单的数据库表,其中包含 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
另一种设定数据种子的方法是在 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方法中执行此操作的优点是
- 这将比使用
AddOrUpdate
更快,因为AddOrUpdate
每次调用数据库以获取任何已经存在的实体。 - 您通常从已知状态(例如空表(开始,因此您可能不需要检查数据是否已存在。注意确保这一点然后,您应该删除
Down
方法中的数据,以便您可以一路撕下来,再撕回去。 - 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));
}
引用:
增量数据种子的最佳方式
准备数据库部署
数据库初始值设定项和迁移种子方法