Tal*_*lon 40 c# entity-framework seeding .net-4.5 ef-migrations
我正在研究迁移,以便清理我们的部署过程.将更改推向生产时所需的人工干预越少越好.
我在迁移系统中遇到了3个主要障碍.如果我无法找到一个干净的方式,他们是显示塞子.
1.如何为每次迁移添加种子数据:
我执行命令"add-migration",它使用Up和Down函数来构建一个新的迁移文件.现在,我想通过Up和Down更改自动更改数据.我不希望将种子数据添加到Configuration.Seed方法,因为它运行所有以各种重复问题结束的迁移.
2.如果无法满足上述要求,我该如何避免重复?
我有一个枚举,我循环,以将值添加到数据库.
foreach(var enumValue in Enum.GetValues(typeof(Access.Level)))
{
context.Access.AddOrUpdate(
new Access { AccessId = ((int)enumValue), Name = enumValue.ToString() }
);
}
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
即使我使用的是AddOrUpdate,我仍然会在数据库中获得重复项.上面的代码将我带到了第三个也是最后一个问题:
3.如何为主键提供种子?
我用以上代码列举的是:
public class Access
{
public enum Level
{
None = 10,
Read = 20,
ReadWrite = 30
}
public int AccessId { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我指定了我想要的值作为我的主键,但实体框架似乎忽略了它.他们最终仍然是1,2,3.我怎么能得到10,20,30?
目前这些EF的局限性还是有意限制,以防止我没有看到的其他类型的灾难?
Col*_*lin 28
Sql("Insert ...").请参阅本页中间的注释:如何插入固定数据[DatabaseGenerated(DatabaseGeneratedOption.None)]属性我认为这是初始化器和种子方法的一个很好的解释
以下是如何使用AddOrUpdate方法的示例:
foreach(var enumValue in Enum.GetValues(typeof(Access.Level)))
{
context.Access.AddOrUpdate(
x => x.Name, //the natural key is "Name"
new Access { AccessId = ((int)enumValue), Name = enumValue.ToString() }
);
}
Run Code Online (Sandbox Code Playgroud)
Gui*_*ino 13
作为一个可能的解决方案项目1,我做了一个实现IDatabaseInitializer,这将运行每个挂起的迁移种子法而已,你将需要实现自定义的策略,IMigrationSeed在每个接口DbMigration类,该Seed方法将被正确后执行Up,并Down每个迁移类的方法.
这有助于为我解决两个问题:
界面看起来像这样
public interface IMigrationSeed<TContext>
{
void Seed(TContext context);
}
Run Code Online (Sandbox Code Playgroud)
下面是将调用此Seed方法的新实现
public class CheckAndMigrateDatabaseToLatestVersion<TContext, TMigrationsConfiguration>
: IDatabaseInitializer<TContext>
where TContext : DbContext
where TMigrationsConfiguration : DbMigrationsConfiguration<TContext>, new()
{
public virtual void InitializeDatabase(TContext context)
{
var migratorBase = ((MigratorBase)new DbMigrator(Activator.CreateInstance<TMigrationsConfiguration>()));
var pendingMigrations = migratorBase.GetPendingMigrations().ToArray();
if (pendingMigrations.Any()) // Is there anything to migrate?
{
// Applying all migrations
migratorBase.Update();
// Here all migrations are applied
foreach (var pendingMigration in pendingMigrations)
{
var migrationName = pendingMigration.Substring(pendingMigration.IndexOf('_') + 1);
var t = typeof(TMigrationsConfiguration).Assembly.GetType(
typeof(TMigrationsConfiguration).Namespace + "." + migrationName);
if (t != null
&& t.GetInterfaces().Any(x => x.IsGenericType
&& x.GetGenericTypeDefinition() == typeof(IMigrationSeed<>)))
{
// Apply migration seed
var seedMigration = (IMigrationSeed<TContext>)Activator.CreateInstance(t);
seedMigration.Seed(context);
context.SaveChanges();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里的好处是你有一个真正的EF上下文来操作种子数据,就像标准的EF种子实现一样.但是,如果您决定删除先前迁移中的种子表,则可能会出现这种情况,您必须相应地重构现有的种子代码.
编辑:作为在Up和Down之后实现种子方法的替代方法,您可以创建相同Migration类的部分类,我发现这很有用,因为它允许我在我想重新播种时安全地删除迁移类同样的迁移.
| 归档时间: |
|
| 查看次数: |
29049 次 |
| 最近记录: |