1

1 から 0..1 へのマッピングを Entity Framework Code First で機能させようとしていますが、エラーが発生し続けます: ReferentialConstraint の依存プロパティがストア生成列にマップされています。列:「ID」。

必須の Location を持つ MainLocation がありますが、Location には複数の子 Location を含めることができるため、Location オブジェクトに MainLocation は必要ありません。

MainLocation は MainLocationAddress と同様の関係にありますが、これは 1 対 1 の関係であり、同じデータベース テーブルを構成します。

ER モデルは次のようになります。 ここに画像の説明を入力

私のエンティティは次のようになります。

[Table("MainLocation")]
public class MainLocation : IEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    public virtual MainLocationAddress Address { get; set; }
    [Required]
    public virtual Location Location { get; set; }
}

[Table("MainLocation")]
public class MainLocationAddress : BaseAddress
{
    [Key, ForeignKey("MainLocation")]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public virtual MainLocation MainLocation { get; set; }
}

public class Location : IEntity
{
    public int Id { get; set; }
    public virtual Location ParentLocation { get; set; }
    public virtual ICollection<Location> ChildLocations { get; set; }
    protected virtual MainLocation MainLocation { get; set; }
    internal MainLocation GetMainLocation() { return this.MainLocation; }
    internal void SetMainLocation(MainLocation mainLocation) { MainLocation = mainLocation; }
}

DbContext クラスの OnModelCreating で関連付けを構成しました。

modelBuilder.Entity<MainLocation>()
            .HasRequired(x => x.Location)
            .WithOptional();

modelBuilder.Entity<MainLocation>()
            .HasRequired(x => x.Address)
            .WithRequiredPrincipal();

PS!Location の MainLocation プロパティは、直接アクセスできないため保護されています。代わりに、Location から値を取得するか、ParentLocation から継承された値を取得するサービス層があります。取得しているエラーに関して変更が加えられたかどうかを確認するために、公開に変更しようとしました。

.WithOptional() を .WithOptional(x => x.MainLocation) に拡張することはできましたが、記載されているエラーに変更はありませんでした。

4

3 に答える 3

1

Person と User という 2 つのエンティティ間で 1:0-1 の関連付けを達成しました。要件として、ユーザーは 1 人の人物のみを持つ必要があります。一方、個人はユーザーに関連付けられている場合と関連付けられていない場合があります。

public class Person
{
    public int PersonId { get; set; }
    public virtual User User { get; set; }
}

public class User
{
    public int UserId { get; set; }
    public int PersonId { get; set; }
    public virtual Person Person { get; set; }
}

次のように EntityTypeConfiguration クラスを定義し、DbContext OnModelCreating メソッドに含めます。

public class PersonConfiguration : EntityTypeConfiguration<Person>
{
    public PersonConfiguration()
    {
        ToTable("People");
        HasKey(p => p.PersonId);
        Property(p => p.PersonId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        HasOptional(p => p.User).WithRequired(u => u.Person); // User is option here but
                                                              // Person is required in User
    }

}

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {

        ToTable("Users");
        HasKey(u => u.UserId);
        Property(u => u.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        // Create a unique index in the Users table on PersonId
        Property(u => u.PersonId).IsRequired().HasColumnAnnotation("Index",
            new IndexAnnotation(new IndexAttribute("IX_PersonId") { IsUnique = true }));

     }

}

DbContext.OnModelCreating メソッドに次の行を追加します。

        modelBuilder.Configurations.Add(new PersonConfiguration());
        modelBuilder.Configurations.Add(new UserConfiguration());

Add-Migration コマンドを実行すると、DbMigration,Up メソッドで次のような結果が得られます。次のように変更します。

        CreateTable(
            "dbo.Users",
            c => new
                {
                    Id = c.String(nullable: false, maxLength: 128),
                    PersonId = c.Int(nullable: false),
                    Person_PersonId = c.Int(nullable: false), // Delete this
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.People", t => t.Person_PersonId) // change to .ForeignKey("dbo.People", t => t.PersonId)
            .Index(t => t.PersonId, unique: true)  // append a ';'
            .Index(t => t._Person_PersonId); // Delete this

        CreateTable(
            "dbo.People",
            c => new
                {
                    PersonId = c.Int(nullable: false, identity: true),
               })
            .PrimaryKey(t => t.PersonId)

Down() メソッドを次のように変更します。

変化する

 DropForeignKey("dbo.Users", "Person_PersonId", "dbo.People");

 DropForeignKey("dbo.AppUsers", "PersonId", "dbo.People");

変化する

 DropIndex("dbo.AppUsers", new[] { "Person_PersonId" });

 DropIndex("dbo.AppUsers", new[] { "PersonId" });

この移行を対象に Update-Database コマンドを実行します。結果の Users テーブルと People テーブルは、PersonId 外部キーに 1 対 1 で関連付けられます。

于 2014-07-25T20:12:43.787 に答える
0

これは、現時点では EF では実現できないことに気付きました (1 対 0..1 関連付け)。

すべての子の場所にメインの場所への参照を持たせることで、私たちのソリューションで解決しました。親の場所がない場所を探すことで、トップの組織を取得できます。ですから、それは私たちが望んでいたものではありませんが、私たちのビジネス モデルを壊すものではありません。

于 2013-10-16T06:46:51.310 に答える