2017-02-22 46 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。这里的问题是,你有两个表格

相关问题