この問題について多くの質問がありますが、私は私のケースを解決できませんでした。誰かがこれを見てください。
Office
およびDoctor
テーブルと1対多の関係を持つSecretary
テーブルがあります。両方の最後のテーブルは、Employee
によって作成された事前定義のUsers
テーブルと共有主キー関係を持つsqlmembershipprovider
テーブルから派生します。 Users
テーブルとRoles
テーブルの間に多くの関係があるようです。
私の問題は、Employee
テーブルとそのUsers
テーブルの間に(ゼロ、1)1)の関係を作成することでした。 (その問題のより良い解決策はありますか?)
---(ここにエラーがあります:
テーブル 'aspnet_UsersInRoles'にFOREIGN KEY制約 'FK_dbo.aspnet_UsersInRoles_dbo.aspnet_Users_UserId'を導入すると、サイクルまたは複数のカスケードパスが発生する場合があります。 ON DELETE NO ACTIONまたはON UPDATE NO ACTIONを指定するか、他の外部キー制約を変更します。制約を作成できませんでした。以前のエラーを参照してください。
ここにリバースエンジニアリング後の私のコードとメンバーシップコードがあります:
public class Office
{
public Office()
{
this.Doctors = new HashSet<Doctor>();
this.Secretaries = new HashSet<Secretary>();
}
[Key]
public System.Guid OfficeId { get; set; }
public virtual ICollection<Doctor> Doctors { get; set; }
public virtual ICollection<Secretary> Secretaries { get; set; }
}
public class Employee
{
[Key, ForeignKey("User")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public System.Guid Id { get; set; }
public string Name { get; set; }
[ForeignKey("Office")]
public System.Guid OfficeId { get; set; }
// shared primary key
public virtual aspnet_Users User { get; set; }
public virtual Office Office { get; set; }
}
public class Doctor :Employee
{
public Doctor()
{
this.Expertises = new HashSet<Expertise>();
}
//the rest..
public virtual ICollection<Expertise> Expertises { get; set; }
}
public class Secretary : Employee
{
// blah blah
}
public class aspnet_Users
{
public aspnet_Users()
{
this.aspnet_Roles = new List<aspnet_Roles>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid UserId { get; set; }
//the rest..
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual ICollection<aspnet_Roles> aspnet_Roles { get; set; }
}
public class aspnet_Roles
{
public aspnet_Roles()
{
this.aspnet_Users = new List<aspnet_Users>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid RoleId { get; set; }
//the rest..
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual ICollection<aspnet_Users> aspnet_Users { get; set; }
}
編集:そして関係がより深くなり、Users
テーブルとApplications
テーブルの間、およびRoles
とApplications
の間にも多対1の関係があります。も。
Fluent APIを使用して、エラーメッセージが示唆するアクションを指定できます。
あなたのコンテキストで:
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<aspnet_UsersInRoles>().HasMany(i => i.Users).WithRequired().WillCascadeOnDelete(false);
}
テーブルaspnet_UsersInRolesの定義が含まれていないため、このコードは機能しない可能性があります。
別のオプションは、これを追加してすべてのCASCADE DELETEを削除することです
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
Fluent APIとの関係の構成に関する詳細が必要な場合は、 http://msdn.Microsoft.com/en-US/data/jj59162 をお勧めします
また、移行クラスを変更できます。私の場合、移行クラスは次のとおりでした。
CreateTable(
"dbo.Spendings",
c => new
{
SpendingId = c.Int(nullable: false, identity: true),
CategoryGroupId = c.Int(nullable: false),
CategoryId = c.Int(nullable: false),
Sum = c.Single(nullable: false),
Date = c.DateTime(nullable: false),
Comment = c.String(),
UserId = c.String(),
LastUpdate = c.String(),
})
.PrimaryKey(t => t.SpendingId)
.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: true)
.ForeignKey("dbo.CategoryGroups", t => t.CategoryGroupId, cascadeDelete: true)
.Index(t => t.CategoryGroupId)
.Index(t => t.CategoryId);
「cascadeDelete:true」を削除すると、Update-Databaseは完全に機能します。
またはfalse
として
.ForeignKey("dbo.Categories", t => t.CategoryId, cascadeDelete: false)
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
このコードをコンテキストに追加します
コメントに基づいて、問題は両方のテーブルで同じPKを使用していることです。それをすぐに変更し、Users PKをEmployeesの追加フィールドとして、UsersとFKの関係(1対1の推測)を持つようにします。そして、独立したPKをユーザーに追加します(他のテーブルを尊重する別のガイド)。 Employeesの新しい外部キー(ユーザーを指すキー)が一意であることを保証したい場合は、常に一意のインデックスを追加できます。
そうすれば、構造をすべて同じに保ち、サイクルを取り除くことができます。
更新:
他の回答からわかるように、削除時にアクションを実行する必要はありません。これを行うための更新された方法は、Entityframework Core 1.0の場合は次のとおりです。
table.ForeignKey(name: "FK_Cities_Regions_RegionId",
column: x => x.RegionId,
principalTable: "Regions",
principalColumn: "RegionId",
onDelete: ReferentialAction.NoAction);
注:ReferentialAction.NoAction
on onDelete