4

私のコードファーストデータベースはうまく機能していました。データベースコンテキストに変更を加えた場合、次にアプリケーションを起動したときにデータベースが更新されます。しかし、その後、データベースにいくつかのモデルを追加し、アプリケーションを再起動したときにこのエラーが発生しました。

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.

奇妙なことの1つは、何も変更せずにアプリケーションを再起動すると、次のエラーが発生することです。

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();
    }
}

からの私の接続文字列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; }
}

public int OrderId { get; set; }更新/注: OrderDetailクラスでコメントアウトすると、プロジェクトは正常に起動します(ただし、 OrderId(もちろん)を追加するための必要な機能は得られません。

4

3 に答える 3

11

この問題は、循環的なカスケード削除の可能性が原因で発生します。これはさまざまな形で発生する可能性がありますが、レコードが2つ以上のカスケード削除ルールによって一度に削除されることになります。

たとえば、親テーブルと2つの子テーブルがあるとします。次に、両方の子テーブルにリンクされている別のテーブルもあります。

Parent
------
ParentId
Name

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

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

SharedChild
-----------
SharedChildId
ChildOneId
ChildTwoId
Name

親テーブルからレコードを削除すると、この削除がChildOneChildTwoの両方にカスケードされる可能性があります。これらの2つの削除は、SharedChildにさらにカスケードされる可能性があり、ここで問題が発生します。SharedChildから同じレコードを削除しようとする2つのパスです。

あなたの状況がまったく同じだと言っているわけではありませんが、どういうわけか、あなたは似たようなことが起こっています。これを解決するために、一方のブランチをチェーンのさらに下流にカスケードさせ、もう一方のチェーンでそれを防ぐことを決定できます。

アプリを初めて実行したとき、およびデータベースを削除するたびにこのエラーが発生する理由は、エラーが発生した時点でEntity Frameworkがデータベースの生成を停止し、データベースが不完全なままになるためです。そのため、他の状況で他のエラーが発生します。

循環カスケード削除の解決についてさらにサポートが必要な場合は、データモデル全体とその関係を表示する必要があります。

于 2012-08-08T14:03:03.817 に答える
2

この問題を解決するには、外部キー属性を削除し、オブジェクトを仮想として参照したままにする必要があります。

これが私がしたことです:

このバグがあったときの古いコード:

    public class OperatingSystemType
{
    public int OperatingSystemTypeID { get; set; }

    [StringLength(50)]
    [Required]
    public string OperatingSystemName { get; set; }

    public int CompanyID { get; set; }

    [ForeignKey("CompanyID")]
    public virtual Company Company { get; set; }
}

このバグを解決した後の新しいコード:

    public class OperatingSystemType
{
    public int OperatingSystemTypeID { get; set; }

    [StringLength(50)]
    [Required]
    public string OperatingSystemName { get; set; }

    public virtual Company Company { get; set; }
}

次に、シードに、以下に示すようなデータを追加します。これは、OperatingSystemTypeのパラメーター値の1つとしてCompanyオブジェクトを追加するだけだからです。

        protected override void Seed(MyAPPMVC.Infrastructure.MyContext context)
    {
        string myusername = "myuser";
        string MicrosoftName = "Microsoft";

        context.Companies.AddOrUpdate(p => p.CompanyName,
            new Company { CompanyName = MicrosoftName, CreatedOn = DateTime.Now, CreatedBy = myusername }
            );

        context.SaveChanges();

        Company MicrosoftCompany = context.Companies.Where(p => p.CompanyName == MicrosoftName).SingleOrDefault();

        context.OperationgSystemTypes.AddOrUpdate(p => p.OperatingSystemName,
            new OperatingSystemType { OperatingSystemName = "Windows 7 Professional", Company = MicrosoftCompany, CreatedOn = DateTime.Now, CreatedBy = myusername },
            new OperatingSystemType { OperatingSystemName = "Windows 8 Professional", Company = MicrosoftCompany, CreatedOn = DateTime.Now, CreatedBy = myusername }
            );
于 2013-05-13T23:47:19.723 に答える
2

OnModelCreatingのコードに関するこの部分を使用して、EFCoreでこの問題を解決しました。

foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
    relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
于 2021-06-10T08:54:01.517 に答える