0

다음 모델이 있습니다. PersonAddress입니다.EF 탐색 속성로드되지 않음

  • PersonAddress 항상 Person

클래스에 속하는 Address

  • 없이 존재할 수 있습니다

    public class Person {  
         // properties 
    
         [ForeignKey("Address")] 
         public int? AddressId { get; set; } 
         public virtual Address Address { get; set; } 
    } 
    
    public class Address { 
         // properties 
    
         [ForeignKey("Person")] 
         public int PersonId { get; set; } 
         public virtual Person Person { get; set; } 
    } 
    

    PersonConfiguration :

    HasOptional(a => a.Address) 
           .WithMany() 
           .HasForeignKey(u => u.AddressId); 
    

    AddressConfiguration :

    HasRequired(a => a.Person) 
          .WithMany() 
          .HasForeignKey(u => u.PersonId); 
    

    문제

    SSMS는 예상대로 모든 FKS과 제약이 있음을 보여줍니다. 다음 작업을 수행 할 그러나 때 반환되는 Person 객체 (주소가있는 사람)의

    var dbPerson = db.Persons.Include(s => s.Address).ToList(); 
    

    없음 Address 또는 AddressId가 채워 없습니다. 모든 것이 null입니다.

    db.Address에 대해 동일한 작업을 수행 할 때 모든 속성이 예상대로 채워집니다. 유효한 관계가 그대로입니다. 내 1 : 1 선택적 관계의 주요 끝이 종속 엔터티를 끌어 들이지 않는 원인은 무엇입니까?

    유의 사항 위에 정의 된대로 두 엔터티에서 액세스 할 수있는 FK ID가 필요합니다..

  • +0

    유창하게 또는 특수 효과를 사용하십시오. 코드는 괜찮아 보인다. 일해야한다. – vijayst

    답변

    2

    One One/Optional 관계가 이와 같이 이루어지지 않았다고 알려드립니다. 나는 코드를 공유하여 1 : 1/0 관계를 만드는 법을 배우고있다. 또한 Fluent API를 사용하는 경우 Data Annotation 속성을 사용할 필요가 없습니다. 그 중 하나만 사용하면 유창한 API가 더 좋아집니다. 관계가 매우 분명해 보입니다.

    1 : 1/0 관계에서 외래 키는 별도로 정의되지 않습니다. 외래 키는 어느 한 테이블에서만 정의되며, 한 엔터티의 기본 키가 다른 관련 엔터티의 기본 키와 외래 키가됩니다. 이 예제에서는 Id 필드를 Person 엔티티 (테이블)의 기본 키로 만들고 Id를 기본 키로 만들고 Address 엔티티 (테이블)의 외래 키로 만들었습니다. 이것은 1 : 1/0 관계의 적절한 방법입니다. 우리가이 협약을 따르지 않는다면 관계가 제대로 이루어지지 않아 문제가 발생합니다.여기

    코드를

    public class Person 
    { 
        // properties 
        public int Id { get; set; } 
        public string Name { get; set; } 
    
        public virtual Address Address { get; set; } 
    } 
    
    public class Address 
    { 
        // properties 
        public int Id { get; set; } 
        public string Location { get; set; } 
    
        public virtual Person Person { get; set; } 
    } 
    
    public class PersonConfiguration : EntityTypeConfiguration<Person> 
    { 
        public PersonConfiguration() 
        { 
         ToTable("Person"); 
         HasKey(p => p.Id); 
    
        } 
    } 
    
    public class AddressConfiguration : EntityTypeConfiguration<Address> 
    { 
        public AddressConfiguration() 
        { 
         ToTable("Address"); 
         HasKey(p => p.Id); 
         Property(a => a.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None); 
    
         HasRequired(p => p.Person) 
          .WithOptional(a => a.Address); 
        } 
    } 
    
    public class AppObjectContext : DbContext 
    { 
        public AppObjectContext() : base("AppConnectionString") 
        { 
    
        } 
    
        public DbSet<Person> People { get; set; } 
        public DbSet<Address> Addresses { get; set; } 
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder) 
        { 
         base.OnModelCreating(modelBuilder); 
    
         modelBuilder.Configurations.Add(new PersonConfiguration()); 
         modelBuilder.Configurations.Add(new AddressConfiguration()); 
        } 
    } 
    

    이며, 여기에 결과 스크린 샷

    스크린 샷에서

    Results

    당신이 우리는 사람 인스턴스와 사람에서 주소 인스턴스를 accesss 수 있습니다 볼 수 있습니다에게 있습니다 매핑 된 관계로 인해 Address 인스턴스의 인스턴스

    여기는 테이블에 넣은 데이터입니다. 여기

    Tables Data 테이블 구조입니다

    Tables Structure

    Person 테이블 SQL 스크립트

    CREATE TABLE [dbo].[Person](
        [Id] [int] IDENTITY(1,1) NOT NULL, 
        [Name] [nvarchar](max) NULL, 
    CONSTRAINT [PK_dbo.Person] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 
    
    GO 
    

    메모에 대한 응답으로 표 SQL 스크립트

    CREATE TABLE [dbo].[Address](
        [Id] [int] NOT NULL, 
        [Location] [nvarchar](max) NULL, 
    CONSTRAINT [PK_dbo.Address] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 
    
    GO 
    
    ALTER TABLE [dbo].[Address] WITH CHECK ADD CONSTRAINT [FK_dbo.Address_dbo.Person_Id] FOREIGN KEY([Id]) 
    REFERENCES [dbo].[Person] ([Id]) 
    GO 
    
    ALTER TABLE [dbo].[Address] CHECK CONSTRAINT [FK_dbo.Address_dbo.Person_Id] 
    GO 
    

    주소 :

    내가 위에서 정의 된 등 모두 실체에 접근 FK ID를 필요합니까 있음을 알아 두셔야합니다.

    1 : 1/0 관계의 규칙에 위배되지만 더 좋은 방법은 다음과 같습니다.

    일대일 관계에서 외래 키와 기본 키 값은 동일합니다. 즉, 한 엔터티의 기본 키 엔터티에 액세스하면 다른 엔터티의 외래 키와 기본 키이기도합니다.

    예를 들어, 사람의 기본 키가 20이면이 사람과 매핑 된 주소의 외래 키와 기본 키도 20입니다. 이는 올바른 액세스 방법입니다.

    -1
    class Program 
    { 
        static void Main(string[] args) 
        { 
         using (var db = new NavigationContext()) 
         { 
          Console.Write("Enter address: "); 
          var addr = Console.ReadLine(); 
    
          Console.Write("Enter person: "); 
          var prs = Console.ReadLine(); 
    
          Address address = new Address { Name = addr }; 
          db.Addresses.Add(address); 
    
          Person person = new Person { Name = prs, AddressID = address.AddressID }; 
          db.Persons.Add(person); 
          db.SaveChanges(); 
    
          Console.WriteLine("Press any key to exit..."); 
          Console.ReadKey(); 
         } 
        } 
    } 
    
    
    [Table("Person")] 
    public class Person 
    { 
        [Key] 
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
        public int PersonID { get; set; } 
        public string Name { get; set; } 
        public int? AddressID { get; set; } 
        //[ForeignKey("AddressID")] 
        //public virtual Address Address { get; set; } 
    } 
    
    [Table("Address")] 
    public class Address 
    { 
        [Key] 
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
        public int AddressID { get; set; } 
        public string Name { get; set; } 
        public int PersonID { get; set; } 
        [ForeignKey("PersonID")] 
        public virtual Person Person { get; set; } 
    } 
    
    
    
    public class NavigationContext : DbContext 
    { 
        public NavigationContext() 
         : base("SQLDBConnection") 
        { 
    
        } 
        public DbSet<Person> Persons { get; set; } 
        public DbSet<Address> Addresses { get; set; } 
    }