实体框架5.0(C#):仅在Update-Database运行两次时才运行种子方法

时间:2013-09-24 13:03:01

标签: c# database entity-framework entity-framework-5 fluent

我有以下型号:

public class User
{
    public int UserId { get; set; }
    public string EmailAddress { get; set; }
    public byte[] PasswordHash { get; set; }
    public byte[] PasswordSalt { get; set; }

    public virtual List<Role> Roles { get; set; }
    public virtual List<Job> Jobs { get; set; }
    public virtual List<Project> Projects { get; set; }
    public virtual List<Submission> Submissions { get; set; }
    public virtual List<PROMembership> PROMemberships { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public string Phone { get; set; }
    public string Notes { get; set; }
    public Guid? PasswordRetrievalToken { get; set; }

    [NotMapped]
    [Display(Name = "Full name")]
    public string FullName
    {
        get
        {
            if ((FirstName != null && FirstName.Length > 0) || (LastName != null && LastName.Length > 0))
            {
                return (FirstName + " " + LastName).Trim();
            }
            else
            {
                return EmailAddress;
            }
        }
    }
}

使用以下流畅的配置类:

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public const int EmailAddressMinLength = 3;
    public const int EmailAddressMaxLength = 62;
    public const int FirstNameMaxLength = 50;
    public const int LastNameMaxLength = 50;
    public const int AddressMaxLength = 100;
    public const int ZipCodeMaxLength = 20;
    public const int CityMaxLength = 50;
    public const int CountryMaxLength = 50;
    public const int PhoneMaxLength = 50;
    public const int NotesMaxLength = 1000;

    public UserConfiguration()
    {
        ToTable("Users");
        HasKey(u => u.UserId).Property(u => u.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        Property(u => u.EmailAddress).IsRequired();
        Property(u => u.EmailAddress).HasMaxLength(EmailAddressMaxLength);
        Property(u => u.PasswordHash).IsRequired();
        Property(u => u.PasswordSalt).IsRequired();
        Property(u => u.FirstName).HasMaxLength(FirstNameMaxLength);
        Property(u => u.LastName).HasMaxLength(LastNameMaxLength);
        Property(u => u.Address).HasMaxLength(AddressMaxLength);
        Property(u => u.ZipCode).HasMaxLength(ZipCodeMaxLength);
        Property(u => u.City).HasMaxLength(CityMaxLength);
        Property(u => u.Country).HasMaxLength(CountryMaxLength);
        Property(u => u.Phone).HasMaxLength(PhoneMaxLength);
        Property(u => u.Notes).HasMaxLength(NotesMaxLength);
        Property(u => u.PasswordRetrievalToken).IsOptional(); // somehow the DB is generated with this field required if this is ommited
        HasMany(u => u.Roles).WithMany(r => r.Users).Map(m => { m.MapLeftKey("UserId"); m.MapRightKey("RoleId"); m.ToTable("UsersInRoles"); });
        HasMany(u => u.Jobs).WithMany(j => j.Composers).Map(m => { m.MapLeftKey("UserId"); m.MapRightKey("JobId"); m.ToTable("ComposersInJobs"); });
    }
}

使用此上下文配置类:

internal sealed class Configuration : DbMigrationsConfiguration<WebProject.DataAccess.WebProjectContext>
{
    private readonly bool _pendingMigrations;

    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
        var migrator = new DbMigrator(this);
        _pendingMigrations = migrator.GetPendingMigrations().Any();
    }

    protected override void Seed(WebProject.DataAccess.WebProjectContext context)
    {
        if (!_pendingMigrations)
            return;
        // imagine seeding code here

到目前为止,这么好。当我执行Update-Database时,一切都按预期工作,数据库正确创建/更新,最后,我的Context-Configuration类中的种子方法被执行。

现在我必须在模型中添加一些字段。使用添加迁移命令:

public partial class AddClientRepresentation : DbMigration
{
    public override void Up()
    {
        AddColumn("dbo.Users", "MiddleName", c => c.String(maxLength: 50));
        AddColumn("dbo.Users", "Company", c => c.String(maxLength: 50));
        AddColumn("dbo.Users", "State", c => c.String(maxLength: 50));
        AddColumn("dbo.Users", "SecondaryPhone", c => c.String(maxLength: 50));
        AddColumn("dbo.Users", "SecondaryEmailAddress", c => c.String(maxLength: 62));
    }

    public override void Down()
    {
        DropColumn("dbo.Users", "SecondaryEmailAddress");
        DropColumn("dbo.Users", "SecondaryPhone");
        DropColumn("dbo.Users", "State");
        DropColumn("dbo.Users", "Company");
        DropColumn("dbo.Users", "MiddleName");
    }
}

所以我有以下课程:

public class User
{
    public int UserId { get; set; }
    public string EmailAddress { get; set; }
    public byte[] PasswordHash { get; set; }
    public byte[] PasswordSalt { get; set; }

    public virtual List<Role> Roles { get; set; }
    public virtual List<Job> Jobs { get; set; }
    public virtual List<Project> Projects { get; set; }
    public virtual List<Submission> Submissions { get; set; }
    public virtual List<PROMembership> PROMemberships { get; set; }

    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string Company { get; set; }
    public string Address { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }
    public string Phone { get; set; }
    public string SecondaryPhone { get; set; }
    public string SecondaryEmailAddress { get; set; }
    public string Notes { get; set; }
    public Guid? PasswordRetrievalToken { get; set; }

    [NotMapped]
    [Display(Name = "Full name")]
    public string FullName
    {
        get
        {
            if ((FirstName != null && FirstName.Length > 0) || (LastName != null && LastName.Length > 0))
            {
                return (FirstName + " " + LastName).Trim();
            }
            else
            {
                return EmailAddress;
            }
        }
    }
}


public class UserConfiguration : EntityTypeConfiguration<User>
{
    public const int EmailAddressMinLength = 3;
    public const int EmailAddressMaxLength = 62;
    public const int FirstNameMaxLength = 50;
    public const int MiddleNameMaxLength = 50;
    public const int LastNameMaxLength = 50;
    public const int CompanyMaxLength = 50;
    public const int AddressMaxLength = 100;
    public const int ZipCodeMaxLength = 20;
    public const int CityMaxLength = 50;
    public const int StateMaxLength = 50;
    public const int CountryMaxLength = 50;
    public const int PhoneMaxLength = 50;
    public const int NotesMaxLength = 1000;

    public UserConfiguration()
    {
        ToTable("Users");
        HasKey(u => u.UserId).Property(u => u.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        Property(u => u.EmailAddress).IsRequired();
        Property(u => u.EmailAddress).HasMaxLength(EmailAddressMaxLength);
        Property(u => u.PasswordHash).IsRequired();
        Property(u => u.PasswordSalt).IsRequired();
        Property(u => u.FirstName).HasMaxLength(FirstNameMaxLength);
        Property(u => u.MiddleName).HasMaxLength(MiddleNameMaxLength);
        Property(u => u.LastName).HasMaxLength(LastNameMaxLength);
        Property(u => u.Company).HasMaxLength(CompanyMaxLength);
        Property(u => u.Address).HasMaxLength(AddressMaxLength);
        Property(u => u.ZipCode).HasMaxLength(ZipCodeMaxLength);
        Property(u => u.City).HasMaxLength(CityMaxLength);
        Property(u => u.State).HasMaxLength(StateMaxLength);
        Property(u => u.Country).HasMaxLength(CountryMaxLength);
        Property(u => u.Phone).HasMaxLength(PhoneMaxLength);
        Property(u => u.SecondaryPhone).HasMaxLength(PhoneMaxLength);
        Property(u => u.SecondaryEmailAddress).HasMaxLength(EmailAddressMaxLength);
        Property(u => u.Notes).HasMaxLength(NotesMaxLength);
        Property(u => u.PasswordRetrievalToken).IsOptional(); // somehow the DB is generated with this field required if this is ommited
        HasMany(u => u.Roles).WithMany(r => r.Users).Map(m => { m.MapLeftKey("UserId"); m.MapRightKey("RoleId"); m.ToTable("UsersInRoles"); });
        HasMany(u => u.Jobs).WithMany(j => j.Composers).Map(m => { m.MapLeftKey("UserId"); m.MapRightKey("JobId"); m.ToTable("ComposersInJobs"); });
    }
}

当我现在运行Update-Database时,迁移运行正常,但不执行Seed方法(无论我是否使用-Force)。 如果我第二次运行Update-Database命令,则会执行种子方法,但会立即返回,因为没有待处理的迁移。

我逐步深入研究,发现如果我在EntityTypeConfiguration中注释掉所有新字段(MiddleName,Company,State,SecondaryPhone,SecondaryEmailAddress),那么第一次运行Update时会执行种子方法命令没有任何问题。

有没有人遇到同样的问题?可能是什么原因?

1 个答案:

答案 0 :(得分:0)

我猜这段代码是罪魁祸首:

if (!_pendingMigrations)
    return;

这是有道理的,为什么它只会第二次运行,因为此时您没有任何待处理的迁移。