0

1 : 0..1 관계에 문제가 있습니다. 오류가 발생합니다 : 'TestContext.Environments'의 엔티티가 'PortalEnvironment_BaEnvironment'관계에 참여합니다. 0 관련 'PortalEnvironment_BaEnvironment_Target'을 찾았습니다. 1 'PortalEnvironment_BaEnvironment_Target'이 (가) 필요합니다.X의 엔티티가 Y 관계에 참여합니다. 0 관련 타겟이 발견되었습니다. 1 대상이 예상됩니다.

나는 Table-Per-Type을 구현하는 3 개의 테이블을 가지고 있습니다.

CREATE TABLE dbo.EnvironmentBase(
    EnvironmentId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED 
); 

CREATE TABLE dbo.BAEnvironment(
    EnvironmentId int NOT NULL PRIMARY KEY CLUSTERED, 
    CONSTRAINT FK_BAEnvironment_EnvironmentBase FOREIGN KEY(EnvironmentId) 
     REFERENCES dbo.EnvironmentBase (EnvironmentId) ON DELETE CASCADE 
); 

CREATE TABLE dbo.PortalEnvironment(
    EnvironmentId int NOT NULL PRIMARY KEY CLUSTERED, 
    BAEnvironmentId int NOT NULL, 
    CONSTRAINT FK_PortalEnvironment_BAEnvironment FOREIGN KEY(BAEnvironmentId) 
     REFERENCES dbo.BAEnvironment (EnvironmentId) , 
    CONSTRAINT FK_PortalEnvironment_EnvironmentBase FOREIGN KEY(EnvironmentId) 
     REFERENCES dbo.EnvironmentBase (EnvironmentId) ON DELETE CASCADE 
); 

내 문제를 통해 작업하는 동안, 나는 Option2Mimic을 활용 One to Zero/One Relationship in EF를 도와의 다음 문서를 중고 (독립 협회 : 아래

내가 내 테스트에 사용하고있는 SQL/C# 코드의 단순화 된 버전입니다) 그게 내 상황에 가장 적합한 것으로 보인다. 그러나 위에 표시된 오류가 발생합니다.

포항 강판은 :

public abstract partial class Environment 
{ 
    public int Id { get; set; } // EnvironmentId (Primary key) 

    public Environment() 
    { 
     InitializePartial(); 
    } 

    partial void InitializePartial(); 
} 

public partial class BaEnvironment : Environment 
{ 
    // MAY have a portal environment 
    public virtual PortalEnvironment PortalEnvironment { get; set; } // PortalEnvironment.FK_PortalEnvironment_BAEnvironment 

    public BaEnvironment() 
    { 
     InitializePartial(); 
    } 

    partial void InitializePartial(); 
} 

public partial class PortalEnvironment : Environment 
{ 
    // MUST have a BAMS environment 
    public virtual BaEnvironment BaEnvironment { get; set; } // PortalEnvironment.FK_PortalEnvironment_BAEnvironment 

    public PortalEnvironment() 
    { 
     InitializePartial(); 
    } 

    partial void InitializePartial(); 
} 

구성을 :

public partial class EnvironmentMap : EntityTypeConfiguration<Environment> 
{ 
    public EnvironmentMap() : this("dbo") 
    { 
    } 

    public EnvironmentMap(string schema) 
    { 
     ToTable("EnvironmentBase", schema); 
     HasKey(x => x.Id); 

     Property(x => x.Id).HasColumnName(@"EnvironmentId") 
      .HasColumnType("int").IsRequired() 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     Property(x => x.Ordinal).HasColumnName(@"Ordinal") 
      .HasColumnType("tinyint").IsRequired(); 

     InitializePartial(); 
    } 
    partial void InitializePartial(); 
} 

public partial class BaEnvironmentMap : EntityTypeConfiguration<BaEnvironment> 
{ 
    public BaEnvironmentMap() : this("dbo") 
    { 
    } 

    public BaEnvironmentMap(string schema) 
    { 
     ToTable("BAEnvironment", schema); 

     InitializePartial(); 
    } 

    partial void InitializePartial(); 
} 

public partial class PortalEnvironmentMap : EntityTypeConfiguration<PortalEnvironment> 
{ 
    public PortalEnvironmentMap() : this("dbo") 
    { 
    } 

    public PortalEnvironmentMap(string schema) 
    { 
     ToTable("PortalEnvironment", schema); 
     //Property(x => x.BaEnvironmentId).HasColumnName(@"BAEnvironmentId") 
      .HasColumnType("int").IsRequired() 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

     // Foreign keys 
     HasRequired(a => a.BaEnvironment).WithOptional(b => b.PortalEnvironment) 
      .Map(c => c.MapKey(@"BAEnvironmentId")); 

     InitializePartial(); 
    } 
    partial void InitializePartial(); 
} 

난 그냥 PortalEnvironment와 BAEnvironment 사이의 관계는 TPT 어떤 문제가 될 것 같지 않습니다. BAEnvironment와 PortalEnvironment 사이의 관계는 1 : 0..1이므로 BAEnviroment는 연관된 PortalEnvironment를 가질 수 있지만 모든 PortalEnvironments는 연관된 BAEnvironment를 가져야합니다.

내 문제는 아주 단순 해 보였지만 앞뒤로 가고 유창한 API 조합으로 해결했습니다.

나는 앱 개발자가 아니라 DBA임을 주목할 가치가있다. 다른 사람들이 그렇게하지 않을 것이기 때문에 그냥 붙어 있어야합니다.

+0

우선 나는 그것이 흥미로운 일 열이있는 테이블 찾기, 왜? – Sami

+0

왜 이러한 엔터티간에 외래 키 _ 및 _ 상속 관계가 있습니까? 그건 . . . 별난. –

+0

@David PortalEnvironment와 BAEnvironment에는 동일한 기능이 있지만 각각에는 다른 속성과 다른 많은 속성이 있으므로 상속이 있습니다. 실제로 TPT 클래스가 몇 가지 더 있습니다.이 두 클래스 간의 관계가 문제이므로 여기에 중점을 둘 것입니다. 상속 자체에 문제가 없습니다. –

답변

0

EF6은 대체 키를 지원하지 않으므로 외래 키 열이 1..1 관계의 엔터티 키가되어야합니다. 고유 한 것으로 FK를 표시 할 수 있지만 EF 모델에서는 BAEnvironment와 포털 환경간에 1..many 관계를 유지합니다.

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
using System.Data.Entity.ModelConfiguration; 
using System.Linq; 

namespace Ef6Test 
{ 

    public abstract partial class Environment 
    { 
     public int Id { get; set; } // EnvironmentId (Primary key) 

     public Environment() 
     { 
      InitializePartial(); 
     } 

     partial void InitializePartial(); 
    } 

    public partial class BaEnvironment : Environment 
    { 
     // MAY have a portal environment 
     [InverseProperty("BaEnvironment")] 
     public virtual ICollection<PortalEnvironment> PortalEnvironments { get; } = new HashSet<PortalEnvironment>(); 

     public BaEnvironment() 
     { 
      InitializePartial(); 
     } 

     partial void InitializePartial(); 
    } 

    public partial class PortalEnvironment : Environment 
    { 
     // MUST have a BAMS environment 
     [ForeignKey("BaEnvironmentID")] 
     public virtual BaEnvironment BaEnvironment { get; set; } // PortalEnvironment.FK_PortalEnvironment_BAEnvironment 

     [Required(), Index(IsUnique = true)] 
     public int BaEnvironmentID { get; set; } 

     public PortalEnvironment() 
     { 
      InitializePartial(); 
     } 

     partial void InitializePartial(); 
    } 
    class Db : DbContext 
    { 
     public DbSet<Environment> Environment { get; set; } 
     public DbSet<BaEnvironment> BaEnvironment { get; set; } 
     public DbSet<PortalEnvironment> PortalEnvironment { get; set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<Environment>().ToTable("Environment"); 
      modelBuilder.Entity<BaEnvironment>().ToTable("BaEnvironment"); 
      modelBuilder.Entity<PortalEnvironment>().ToTable("PortalEnvironment"); 

      modelBuilder.Entity<PortalEnvironment>().HasRequired<BaEnvironment>(e => e.BaEnvironment).WithMany(); 
      base.OnModelCreating(modelBuilder); 
     } 
    } 




    class Program 
    { 
     static void Main(string[] args) 
     { 

      Database.SetInitializer(new DropCreateDatabaseAlways<Db>()); 

      using (var db = new Db()) 
      { 

       db.Database.Log = m => Console.WriteLine(m); 
       db.Database.Initialize(true); 


      } 

      Console.WriteLine("Hit any key to exit"); 
      Console.ReadKey(); 
     } 
    } 
} 
+0

나는 그 모델에서 유일 제한을 벗어나야 만했다. 소스가 아니기 때문에 대상과 관련이 없습니다. –

+0

확실히 관련이 있습니다. PortalEnvironment.BAEnvironmentId가 UNIQUE가 아닌 경우 여러 PortalEnvironment 행이 동일한 BAEnvironment 행을 참조 할 수 있으며 관련성은 1.Many입니다. EF는 1-1 관계가 외부 키로 Key를 사용하고 EF6이 Entity 당 하나의 Key만을 지원하도록 요구합니다. –

+0

내가 의미하는 것은 내가 그렇게까지까지 가지지 않는다는 것이다. 내 원래 테스트 모델에는 고유 한 제약 조건이 없습니다. 오류를 내지 않고도 컴파일되지 않습니다. 따라서 제약 조건은 현재의 문제와 관련이 없습니다.내일 당신의 솔루션에 더 가까이 다가 갈 것입니다. 감사! –