EntityFramework CodeFirst中未调用种子方法

15

我从4.1版本开始一直在苦苦挣扎这个问题(现在我使用的是4.3版本)。在我看来,为了调用种子方法,我只需要执行以下步骤:

1)在SQL Server上创建一个空的数据目录 2)执行以下代码:

Database.SetInitializer(new DropCreateDatabaseAlways<SiteDB>());

我已经定义了我的SiteDB,如下所示:

public class SiteDBInitializer : 
    DropCreateDatabaseAlways<SiteDB>
{
    protected override void Seed(SiteDB db)
    {
           ... (break point set here that never gets hit)

我感觉一定是漏掉了非常简单的东西,因为这个代码可以创建表格,但从未调用seed方法。

为了更清晰地说明,这里是包含所有代码的完整示例。当我运行它时,seed从未被调用:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Data.Entity;

namespace ConApp
{
internal class Program
{
    private static void Main(string[] args)
    {
        Database.SetInitializer(new SiteDBInitializer());
        using (var db = new SiteDB())
        {
            var x = db.Customers;
        }
    }
}

public class SiteDB : DbContext
{
    public DbSet<Customer> Customers { get; set; }
}

public class Customer
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    public string LastName { get; set; }
}

public class SiteDBInitializer :
    DropCreateDatabaseAlways<SiteDB>
{
    protected override void Seed(SiteDB db)
    {
        db.Customers.Add(new Customer() {LastName = "Kellner"});
        db.Customers.Add(new Customer() {LastName = "Jones"});
        db.Customers.Add(new Customer() {LastName = "Smith"});
        db.SaveChanges();
    }
}

}
2个回答

8
你需要调用Database.SetInitializer(new SiteDBInitializer());代替之前的方法。

1
我猜你的意思是:Database.SetInitializer(new SiteDBInitializer()); 我尝试了一下,但它也没有起作用。 - Peter Kellner
1
@PeterKellner 当你第一次执行某些操作(例如查询)时,它会被调用。你尝试过执行查询吗? - Eranga
嗨,Eranga和J.W. 我更新了我的问题,包括一个微不足道的控制台应用程序,我相信种子应该被调用,但实际上并没有。如果你们能看一下(甚至粘贴并运行它),我会非常感激。我确定我错过了一些简单的东西,但这已经让我疯狂了几个月。 - Peter Kellner
@PeterKellner你的示例没有查询数据库。请将“var x = db.Customers;”替换为“var x = db.Customers.ToList();”。 - Eranga
1
谢谢,Eranga,你说得完全正确,这确实解决了我的问题。当我调用“Database.SetInitializer(new SiteDBInitializer());”时,似乎每次都会重新创建我的数据库。我该如何编写初始化程序,以便第一次创建数据库(如果不存在)并进行种子填充,然后在此之后不再重新创建数据库?我一直在尝试使用DropCreateDatabaseIfModelChanges,但似乎它不能在第一次创建数据库时创建它。 - Peter Kellner
3
我最终厌倦了对所有这些是如何运作的不真正理解,所以今天早上我花了几个小时写了三篇博客文章来解释一切。感谢大家的帮助。http://peterkellner.net/2012/02/17/entityframework-4-3-codefirst-trivial-one-file-example-part-1/ - Peter Kellner

0

我查看了所有相关答案,但是没有一个真正有效的方法,我想知道这是否是 Microsoft 的 Bug——如果 DB 不存在就不调用 Seed 方法。 唯一有效的代码是:当 DB 不存在时,让该类实际调用 Seed 方法:

上下文类:

class AlisDbContext : DbContext
{
    public class MyContextFactory : IDbContextFactory<AlisDbContext>
    {
        public AlisDbContext Create()
        {
            return new AlisDbContext("CompactDBContext");
        }
    }

    public AlisDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
    {
        Database.SetInitializer(new AlisDbInitializer(this));
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<AlisDbContext>());
    }

    public DbSet<SavedCredentials> SavedCredentialses { get; set; }
}

然后AlisDbInitializer需要检查并调用种子方法,如下:

public AlisDbInitializer(AlisDbContext alisDbContext)
    {
        if (!alisDbContext.Database.Exists())
        {
            Seed(alisDbContext);
        }          
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接