2017-02-22 44 views
10

基本上我有這樣一個實體:如何將類屬性(使用導航道具)作爲實體屬性?複雜類型不會做

public class Person { 
public int PersonId { get; set; } 
public string Name { get; set; } 
public Address Hometown { get; set; } 
} 

又像類:

public class Address { 
public City City { get; set; } 
public string Province { get; set; } 
} 

我想做到的是有垂直連接兩個階級,有一個表具有行:

TB_PERSON: 
    PersonId PK 
    Name 
    City_id FK 
    Province 

爲什麼我想這個做法是,在我的實際項目中,我有相同類型的數據結構模式的出現對多個條目,在這樣的案例就是地址類。它可能很容易出現在另一個實體中。

難道這幾天很難找到如何做到這一點?最近我可以得到的是複雜的類型,但在這種情況下它們不允許導航屬性。我想訪問並獲得我的行數據結構化和麪向對象,認爲EF會有幫助。任何幫助表示讚賞。

+0

'public Auth Auth'你的變量名和類型不能相同。你可以通過'myPerson.auth.cardType'和'myPerson.auth'來訪問'CardType'和'WhateverField' .whateverField' –

+0

感謝您的回答,但請親切地說,這不是我要求的 –

回答

3

的ComplexType應該是一個解決方案,但遺憾的是:

複雜類型不能包含導航屬性。 Source

變通方法的列表:

解決方法與表分裂

public class Person 
{ 
    public int PersonID { get; set; } 
    public string Name { get; set; } 
    public virtual Address Address { get; set; } 
} 

public class Address 
{ 
    public Int32 ID { get; set; } 
    public string Province { get; set; } 
    public virtual City City { get; set; } 

} 

public class City 
{ 
    public Int32 CityID { get; set; } 
    public string Name { get; set; } 
} 

public class MappingContext : DbContext 
{ 
    public DbSet<Person> Persons { get; set; } 

    public DbSet<Address> Addresses { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Address>() 
      .HasKey(t => t.ID) 
      .HasOptional(t => t.City) 
      .WithMany() 
      .Map(t => t.MapKey("CityID")); 

     modelBuilder.Entity<Address>() 
      .Property(t => t.ID) 
      .HasColumnName("PersonID"); 

     modelBuilder.Entity<Person>() 
      .HasKey(t => t.PersonID) 
      .HasRequired(t => t.Address) 
      .WithRequiredPrincipal(); 

     modelBuilder.Entity<Person>().ToTable("TB_PERSON"); 

     modelBuilder.Entity<Address>().ToTable("TB_PERSON"); 

     modelBuilder.Entity<City>() 
      .HasKey(t => t.CityID) 
      .ToTable("City"); 
    } 
} 

[使用方法]

using (var db = new MappingContext()) 
    { 
     var person = db.Persons.FirstOrDefault(); 
     var cityName = person.Address.City.Name; 

     var address = db.Addresses.FirstOrDefault(); 
     var personName = address.Person.Name; 
    } 

[數據庫]

CREATE TABLE [dbo].[City](
     [CityID] [int] IDENTITY(1,1) NOT NULL, 
     [Name] [varchar](50) NULL 
    ) ON [PRIMARY] 

    CREATE TABLE [dbo].[TB_PERSON](
     [PersonId] [int] IDENTITY(1,1) NOT NULL, 
     [Name] [varchar](50) NULL, 
     [Province] [varchar](50) NULL, 
     [CityID] [int] NULL 
    ) ON [PRIMARY] 

解決方法與表分裂+ TPC繼承(可重複使用的地址類)

TB_CUSTOMER與地址列另一個表。

public class Person 
{ 
    public int PersonID { get; set; } 
    public string Name { get; set; } 
    public virtual PersonAddress Address { get; set; } 
} 

public class Address 
{ 
    public string Province { get; set; } 
    public virtual City City { get; set; } 

} 

public class PersonAddress : Address 
{ 
    public Int32 PersonID { get; set; } 
    public virtual Person Person { get; set; } 
} 
public class CustomerAddress : Address 
{ 
    public Int32 CustomerID { get; set; } 
} 

public class Customer 
{ 
    public int CustomerID { get; set; } 
    public string Name { get; set; } 
    public virtual CustomerAddress Address { get; set; } 
} 

public class City 
{ 
    public Int32 CityID { get; set; } 
    public string Name { get; set; } 
} 

public class MappingContext : DbContext 
{ 
    public DbSet<Person> Persons { get; set; } 
    public DbSet<Customer> Customers { get; set; } 
    public DbSet<PersonAddress> PersonAddresses { get; set; } 
    public DbSet<CustomerAddress> CustomerAddresses { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<PersonAddress>() 
      .HasKey(t => t.PersonID) 
      .HasOptional(t => t.City) 
      .WithMany() 
      .Map(t => t.MapKey("CityID")); 

     modelBuilder.Entity<CustomerAddress>() 
      .HasKey(t => t.CustomerID) 
      .HasOptional(t => t.City) 
      .WithMany() 
      .Map(t => t.MapKey("CityID")); 

     modelBuilder.Entity<Person>() 
      .HasRequired(t => t.Address) 
      .WithRequiredPrincipal(t => t.Person); 

     modelBuilder.Entity<Customer>() 
      .HasRequired(t => t.Address) 
      .WithRequiredPrincipal(); 

     modelBuilder.Entity<Person>().ToTable("TB_PERSON"); 
     modelBuilder.Entity<PersonAddress>().ToTable("TB_PERSON"); 

     modelBuilder.Entity<Customer>().ToTable("TB_CUSTOMER"); 
     modelBuilder.Entity<CustomerAddress>().ToTable("TB_CUSTOMER"); 

     modelBuilder.Entity<City>() 
      .HasKey(t => t.CityID) 
      .ToTable("City"); 
    } 
} 

解決方法與IAddress

public class Person : IAddress 
{ 
    public int PersonID { get; set; } 
    public string Name { get; set; } 
    public string Province { get; set; } 
    public virtual City City { get; set; } 

    [NotMapped] 
    public IAddress Address { get { return this; } } 
} 

public interface IAddress 
{ 
    string Province { get; set; } 
    City City { get; set; } 

} 

public class City 
{ 
    public Int32 CityID { get; set; } 
    public string Name { get; set; } 
} 

public class MappingContext : DbContext 
{ 
    public DbSet<Person> Persons { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 

     modelBuilder.Entity<Person>() 
      .HasKey(t => t.PersonID) 
      .HasOptional(t => t.City) 
      .WithMany() 
      .Map(t => t.MapKey("CityID")); 

     modelBuilder.Entity<Person>().ToTable("TB_PERSON"); 

     modelBuilder.Entity<City>() 
      .HasKey(t => t.CityID) 
      .ToTable("City"); 
    } 
} 
+0

感謝您的回答我不知道表拆分。但是這個班級發生的不止一個條目,所以如果我去分表,我必須爲每個其他實體做這件事。 –

+0

+1表格拆分。有了這個模型,同樣從Address到Person(具有複雜類型,您沒有此功能)中刪除導航屬性,您需要爲每個使用它的實體設置Address類(例如,在此情況下,一個用於客戶等)我是對的嗎? – bubi

+0

你說得對,地址不必具有導航屬性給Person(爲人做這個配置應該以.WithRequiredPrincipal();)結尾。 要在其他映射(例如客戶)中重用Address類,我認爲我們需要將Table Splitting和Address的一些繼承策略(如TPC)結合起來。 可重用地址類將成爲基類。 PersonAddress和CustomerAddress將具有Person和Customer的其他屬性,並且它們將與Table Splitting策略一起映射。 – Daprpaz

0

幾乎每一個複雜的導航,可以用流利的API。

谷歌這些:流暢API和EntityTypeConfiguration

+0

謝謝我會尋找這些,同時你可以改善你的答案,並提供一個解決方案,所以我可以將你的答覆標記爲接受答案 –

1

也有除表拆分2個解決方法(不解決方案)。

繼承

創建地址類,並從它在每一個應該有一個地址類繼承。
地址屬性與其他屬性混合(實際上,我認爲我不會在您的情況下應用此解決方案)。

1-1關係
(或n-1,如果多個實體可以共享相同的地址的關係)

型號:

public class ClassA 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public virtual ClassB ClassB { get; set; } 
} 

public class ClassB 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public virtual ClassA ClassA { get; set; } 
} 

上下文:

class Context : DbContext 
{ 
    public Context(DbConnection connection) 
     : base(connection, false) 
    { } 

    public DbSet<ClassA> As { get; set; } 
    public DbSet<ClassB> Bs { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<ClassB>().HasOptional(c => c.ClassA).WithOptionalDependent(c => c.ClassB); 
    } 
} 

DDL報表:

ExecuteNonQuery========== 
CREATE TABLE [ClassAs] (
[Id] int not null identity(1,1) 
, [Description] text null 
); 
ALTER TABLE [ClassAs] ADD CONSTRAINT [PK_ClassAs_9cd06620] PRIMARY KEY ([Id]) 
ExecuteNonQuery========== 
CREATE TABLE [ClassBs] (
[Id] int not null identity(1,1) 
, [Description] text null 
, [ClassA_Id] int null 
); 
ALTER TABLE [ClassBs] ADD CONSTRAINT [PK_ClassBs_9cd06620] PRIMARY KEY ([Id]) 
ExecuteNonQuery========== 
CREATE INDEX [IX_ClassA_Id] ON [ClassBs] ([ClassA_Id]) 
ExecuteNonQuery========== 
ALTER TABLE [ClassBs] ADD CONSTRAINT [FK_ClassBs_ClassAs_ClassA_Id] FOREIGN KEY ([ClassA_Id]) REFERENCES [ClassAs] ([Id]) 

在第二種情況下,您可以刪除ClassB.ClassA導航屬性,以便您可以在多個類型中共享ClassB。這裏的問題是,你有兩個表格

相關問題