在表上引入FOREIGN KEY约束可能会导致循环或多个级联路径导致Database.SetInitializer不起作用?

Ecn*_*lyr 4 asp.net-mvc database-design entity-framework asp.net-mvc-3 entity-framework-4.3

我的代码优先数据库工作得很好.如果我对数据库上下文进行了更改,则下次启动应用程序时将更新数据库.但后来我在数据库中添加了一些模型,并在重新启动应用程序时出现此错误:

Introducing FOREIGN KEY constraint 'FK_OrderDetails_Orders_OrderId' on table 'OrderDetails' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.

其中一个奇怪的事情是,如果我再次启动应用程序而不更改任何内容,那么我会收到此错误:

Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.

为了再次发生第一个错误,我必须删除我的.mdf和.ldf文件(数据库),并用我的修订历史记录中的副本替换.mdf文件.

世界上为什么会发生这种情况?


以供参考:

我的Global.asax.cs文件在Application_Start()方法中有这个:

Database.SetInitializer<EfDbContext>(new EfDbContextInitializer());

看起来像这样:

public class EfDbContextInitializer : DropCreateDatabaseIfModelChanges<EfDbContext>
{
    protected override void Seed(EfDbContext context)
    {
        var orders = new List<Order>
            {
                . . .
            };
        orders.ForEach(s => context.Orders.Add(s));
         . . . etc. . .
        context.SaveChanges();
    }
}
Run Code Online (Sandbox Code Playgroud)

我的连接字符串来自Web.config:

<add name="EFDbContext" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;database=pos;AttachDBFilename=|DataDirectory|pos.mdf;MultipleActiveResultSets=true;User Instance=true" providerName="System.Data.SqlClient" />

最后,我的Order和OrderDetails模型(第一个错误是直接引用的):

public class Order
{
    public int OrderId { get; set; }

    public List<OrderDetail> OrderDetails { get; set; }

    public int EstablishmentId { get; set; }

    public virtual Establishment Establishment { get; set; }
}

public class OrderDetail
{
    public int OrderDetailId { get; set; }

    public int OrderId { get; set; }

    public int ProductId { get; set; }

    public int Quantity { get; set; }

    public decimal UnitPrice { get; set; }

    public virtual Product Product { get; set; }

    public virtual Order Order { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

更新/注意:如果我public int OrderId { get; set; }在我的OrderDetail类中注释掉,项目启动正常(虽然我没有获得所需的添加功能OrderId(当然).

Kri*_*aes 11

此问题是由可能的循环级联删除引起的.这可以以多种形式发生,但它归结为一次由两个或多个级联删除规则删除的记录.

例如,假设您有父表和两个子表.然后你还有另一个表链接到两个子表:

Parent
------
ParentId
Name

ChildOne
--------
ChildOneId
ParentId
Name

ChildTwo
--------
ChildTwoId
ParentId
Name

SharedChild
-----------
SharedChildId
ChildOneId
ChildTwoId
Name
Run Code Online (Sandbox Code Playgroud)

从Parent表中删除记录时,此删除可能会同时连接到ChildOne ChildTwo.这两个删除可以进一步级联到SharedChild,这里我们得到问题:两个路径试图从SharedChild删除相同的记录.

我并不是说你的情况完全一样,但无论如何,你有类似的事情发生.要解决这个问题,您可以决定允许一个分支在链中进一步级联,并在另一个链中阻止它.

您第一次运行应用程序然后每次删除数据库时都会收到此错误的原因是因为(我相信)实体框架在发生错误时停止生成数据库,并且您将留下不完整的数据库.这就是为什么你在其他情况下得到另一个错误的原因.

如果您需要更多帮助来解决循环级联删除,您可能需要显示整个数据模型及其关系.