2017-02-22 13 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' Ваше имя и тип переменной не могут быть идентичными. Вы можете получить доступ к« CardType »и« WhateverField », выполнив« myPerson.auth.cardType »и« myPerson.auth » .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 (для многократного использования класса Address)

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, как в этом случае, один для клиента и т. д.) Я прав? – bubi

+0

Вы правы, адрес не должен иметь свойство навигации для Лица (для этой конфигурации для человека должно быть выполнено .WithRequiredPrincipal();). Чтобы повторно использовать класс Address в другом сопоставлении (например, Customer), мне кажется, нам нужно объединить разделение таблицы с некоторой стратегией наследования для адреса (например, TPC). Класс многоразового адреса будет базовым классом. PersonAddress и CustomerAddress будут иметь дополнительные свойства для Person и Customer, и они будут сопоставлены с стратегией разделения таблиц. – Daprpaz

0

Почти каждый комплекс навигации можно с беглым апи.

Google Это: свободный Апи и EntityTypeConfiguration

+0

Спасибо, я буду искать их, пока вы можете улучшить свой ответ и предоставить решение, чтобы я мог отметить ваш ответ в качестве принятого ответа –

1

Есть также более 2 обходной путь (не решения) в дополнение к таблице расщепления.

Наследование

Создание адреса класса и наследовать от него в каждом классе, который должен иметь адрес.
Свойства адреса смешиваются с другими свойствами (так что, на самом деле, я думаю, что я бы не применил это решение в вашем случае).

1-1 отношения
(или п-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 с несколькими типами. Проблема здесь в том, что у вас есть 2 таблицы

Смежные вопросы