簡體   English   中英

編寫第一個實體框架(EF6)的代碼,在初始創建后添加多對多關系

[英]Code first Entity Framework (EF6) Adding Many-to-Many relationship after initial create

我是MVC,實體框架和數據庫的新手,但我無法弄清楚這里發生了什么。 我試圖通過已經創建的數據庫中的代碼創建多對多關系。 在此先感謝您提供的任何提示。

我有一個由2個模型定義的代碼優先數據庫(實際的數據庫要復雜得多,但為簡潔起見,這也顯示了我的問題)。

public class Beer
{
    public int BeerID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Company> Companies { get; set; }  // one beer could have many companies

}

public class Company
{
    public int CompanyID { get; set; }
    public string Name { get; set; }

    // Navigation Property

}

public class ManyToManyDB : DbContext
{
    public DbSet<Beer> Beers { get; set; }
    public DbSet<Company> Companies { get; set; }
}

當我運行Enable-Migrations -ContextTypeName ManyToManyTest.Models.ManyToManyDB時,一切都很好。 我在項目中獲得Configuration.cs文件。 我在那里做一些編輯:

    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }

將一些數據添加到Seed方法中:

        context.Companies.AddOrUpdate(c => c.Name,
            new Company { Name = "Company1" },
            new Company { Name = "Company2" },
            new Company { Name = "Company3" }
            );

        context.Beers.AddOrUpdate(b => b.Name,
            new Beer { Name = "Beer1" },
            new Beer { Name = "Beer2" },
            new Beer { Name = "Beer3" }
            );

現在,我運行“ Update-Database -verbose”,並創建了數據庫。 到現在為止還挺好。

現在說我忘了在Company類中創建多對多關系,因此我對其進行了更新:

public class Company
{
    public int CompanyID { get; set; }
    public string Name { get; set; }

    // Navigation Property
    public virtual ICollection<Beer> Beers { get; set; }  // this is what I forgot, a company can have many beers
}

好的,所以,因為這是開發的早期階段,所以我應該能夠再次運行“ update-database”,它將添加必要的內容(在這種情況下,它將包括一個用於多對多的新聯結表關系)。 不幸的是,當我這樣做時,會發生:

EXECUTE sp_rename @objname = N'dbo.Companies', @newname = N'CompanyBeers', @objtype = N'OBJECT'

警告:更改對象名稱的任何部分都可能會破壞腳本和存儲過程。

IF object_id(N'[dbo].[FK_dbo.Companies_dbo.Beers_Beer_BeerID]', N'F') IS NOT NULL
    ALTER TABLE [dbo].[Companies] DROP CONSTRAINT [FK_dbo.Companies_dbo.Beers_Beer_BeerID]

引發此異常

System.Data.SqlClient.SqlException (0x80131904): Cannot find the object "dbo.Companies" because it does not exist or you do not have permissions.

錯誤為:找不到對象“ dbo.Companies”,因為該對象不存在或您沒有權限。

知道為什么在創建初始數據庫模式后無法創建多對多關系嗎?

我可能只是從頭開始嘗試,但是想知道是否有解決方案,以防將來發生這種情況。

如果重要的話,請使用VS2013和EF6.02。 該項目來自普通的MVC模板。

抱歉地說,但這似乎是EF中的錯誤。 EF生成的自動更新與運行“添加遷移”所產生的更新相同。

    public override void Up()
    {
        RenameTable(name: "dbo.Companies", newName: "CompanyBeers");
        DropForeignKey("dbo.Companies", "Beer_BeerID", "dbo.Beers");
        DropIndex("dbo.Companies", new[] { "Beer_BeerID" });
        CreateIndex("dbo.CompanyBeers", "Company_CompanyID");
        CreateIndex("dbo.CompanyBeers", "Beer_BeerID");
        AddForeignKey("dbo.CompanyBeers", "Company_CompanyID", "dbo.Companies", "CompanyID", cascadeDelete: true);
        AddForeignKey("dbo.CompanyBeers", "Beer_BeerID", "dbo.Beers", "BeerID", cascadeDelete: true);
        DropColumn("dbo.Companies", "Beer_BeerID");
    }

現在,在遷移方法的第二行中,它調用DropForeignKey,它產生帶有DROP的ALTER TABLE並以異常結尾,因為表是首先被重命名的。

解決方法是運行Add-Migration,刪除代碼並手動編寫。 我最終得到了這樣的代碼:

    public override void Up()
    {
        DropIndex("dbo.Companies", new[] { "Beer_BeerID" });
        DropForeignKey("dbo.Companies", "Beer_BeerID", "dbo.Beers");
        DropColumn("dbo.Companies", "Beer_BeerID");

        CreateTable(
            "dbo.CompanyBeers",
            c => new
            {
                Company_CompanyID = c.Int(nullable: false),
                Beer_BeerID = c.Int(nullable: false),
            })
            .PrimaryKey(t => new { t.Company_CompanyID, t.Beer_BeerID })
            .ForeignKey("dbo.Companies", t => t.Company_CompanyID, cascadeDelete: true)
            .ForeignKey("dbo.Beers", t => t.Beer_BeerID, cascadeDelete: true)
            .Index(t => t.Company_CompanyID)
            .Index(t => t.Beer_BeerID);
    }

回答我自己的問題。 經過數小時的思考,就像pg0xC指出的那樣,它可能是實體框架中的錯誤。 如果其他人遇到此問題,這是一個簡單的解決方法。

繼續上面的示例,從Beer和Company類中刪除這兩個ICollection:

public class Beer
{
    public int BeerID { get; set; }
    public string Name { get; set; }
    //public virtual ICollection<Company> Companies { get; set; }  // one beer could have many companies

}

public class Company
{
    public int CompanyID { get; set; }
    public string Name { get; set; }

    // Navigation Property
    // public virtual ICollection<Beer> Beers { get; set; }  // this is what I forgot, a co
}

現在再次運行update-database ...它對示例和實際代碼都有效。 當然,您將失去與啤酒相關的任何公司。 如果這是不可接受的,則您將必須執行與其他應答程序(pg0xC)所述類似的操作。

返回並取消對Beer和Company類中的ICollection的注釋,最后一次運行update-database,一切都應該正常工作。 完成此操作后,我在localdb中有了CompanyBeers聯結表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM