0

我有以下型號 - PersonAddressEF導航屬性不加載

  • Person未經Address
  • Address總是屬於Person

類可以存在:

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和約束是按預期方式。然而,當我做到以下幾點:

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

返回Person對象(那些有地址)都沒有填充AddressAddressId。一切都是空的。

當我對db.Address執行相同的操作時,我得到的所有屬性都按預期方式填充 - 有效的關係觸發。是什麼導致我的1:1可選關係的主體結束不拉入相關實體?

我應該注意,我確實需要FK ID在上面定義的上定義的兩個實體上。

+0

使用流利或註釋。代碼看起來沒問題。應該管用。 – vijayst

回答

2

讓我告訴你,One-One/Optional關係不是這樣的。我分享代碼如何使1:1/0關係。 另外,當您使用流暢的API時,不需要使用數據註解屬性。只使用其中的一個,流利的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

在截圖中,你可以看到,我們可以從Person實例和個人accesss Address實例來自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關係的約定,但更好的方法如下。

在一對一關係中,外鍵和主鍵值是相同的,也就是說,如果你訪問一個實體的主鍵實體,它也是另一個實體的外鍵和主鍵。

例如,如果person的主鍵是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; } 
}