【问题标题】:Entity Framework 5.0 (C#): Seed method only run if Update-Database is run twiceEntity Framework 5.0 (C#):种子方法仅在 Update-Database 运行两次时运行
【发布时间】:2013-09-24 13:03:00
【问题描述】:

我有以下型号:

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),则在我第一次运行更新时会执行种子方法命令没有任何问题。

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

【问题讨论】:

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


    【解决方案1】:

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

    if (!_pendingMigrations)
        return;
    

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

    【讨论】:

    • 当我使用“Add-Migration”命令添加新字段时,应该有一个挂起的迁移。正如我所说,如果我注释掉 EntityTypeConfiguration 中的新字段...
    • 至少,我加了一个“throw Exception();”在种子方法的开头,因为我不信任 Update-Database 的输出(“运行种子方法。”)。我想确保 Seed() 真的被调用/未被调用。
    猜你喜欢
    • 1970-01-01
    • 2016-09-17
    • 2013-04-30
    • 2020-02-25
    • 2015-11-29
    • 1970-01-01
    • 2018-10-02
    • 2014-08-15
    • 1970-01-01
    相关资源
    最近更新 更多