我是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”并创建数据库。到目前为止一切都很好。
现在假设我忘了在公司课程中创建我的多对多关系,所以我更新它:
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模板。
答案 0 :(得分:1)
很抱歉,但这似乎是EF中的一个错误。 EF生成的自动更新等于通过运行Add-Migration生成的更新。
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,该DROP以异常结束,因为表首先被重命名。
解决方法是运行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);
}
答案 1 :(得分:0)
回答我自己的问题。经过几个小时的思考后,像pg0xC一样,它可能是实体框架中的一个错误。如果其他人遇到此问题,这是一个简单的解决方法。
坚持上面的示例,从Beer和Company类中删除两个ICollections:
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类中的ICollections,最后一次运行update-database,一切都应该有效。执行此操作后,我在localdb中有了CompanyBeers联结表。