2012-11-06 38 views
4

我试了一整天才得到这个工作。我学到了很多关于EF的Fluent API(例如this是一篇很好的文章),但是我没有成功。实体框架5中的一对一和一对多关系代码优先

我有三个实体:

public class Address 
{ 
    [Key] 
    public virtual int AddressId { get; set; } 
    public virtual string AddressString { get; set; } 
} 
public class User 
{ 
    [Key] 
    public virtual int UserId { get; set; } 
    public virtual ICollection<Address> Addresses { get; set; } 
} 
public class House 
{ 
    [Key] 
    public virtual int HouseId { get; set; } 
    public virtual Address Address { get; set; } 
} 

,并在

protected override void OnModelCreating(DbModelBuilder modelBuilder) 

试过,我能想到的HasMany, HasOptional, WithOptional, WithOptionalDependentWithOptionalPrincipial所有组合两个UserHouse我只是无法得到它的工作。我认为应该清楚,我想要什么。一个用户可能有多个地址(首先我想强制至少一个地址,但现在如果用户可能有地址可选,我会很高兴),而一个房子只有一个地址 - 这是需要。如果房子的地址会被级联删除,那将会很好。

回答

3

我相信以下几点应该适合你

public class Address 
{ 
    public int AddressId { get; set; } 
    public string AddressString { get; set; } 
} 

public class User 
{ 
    public int UserId { get; set; } 
    public virtual ICollection<Address> Addresses { get; set; } 
} 

public class House 
{ 
    public int HouseId { get; set; } 
    public virtual Address Address { get; set; } 
} 

public class TestContext : DbContext 
{ 
    public DbSet<Address> Addresses { get; set; } 
    public DbSet<User> Users { get; set; } 
    public DbSet<House> Houses { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<User>().HasMany(u => u.Addresses).WithMany(); 
     modelBuilder.Entity<House>().HasRequired(h => h.Address).WithOptional().Map(m => m.MapKey("AddressId")); 
    } 
} 

请注意,通常情况下最好是自己指定外键字段,这可以让您以后的生活更加轻松。如果你这样做,那么你可以选择重写阁为以下几点:

public class House 
{ 
    public int HouseId { get; set; } 
    public int AddressId { get; set; } 
    public virtual Address Address { get; set; } 
} 

公约将连接AddressId和地址。如果你有房子和地址之间有一个一对一映射,你也可以将它们链接在他们的主键:

public class House 
{ 
    [ForeignKey("Address")]    
    public int HouseId { get; set; } 
    public virtual Address Address { get; set; } 
} 

你提到你想执行至少一个地址 - 这是不可能的与一对多的关系。如果用户只有一个地址,则只能这样做,此时可以在User类上添加必需的AddressId属性。

一个其他的评论 - 你在你的代码中做了一切虚拟。您只需要使导航属性变为虚拟。

+0

好吧,今天有更多的睡眠,我想我的问题是在初始化,而不是在上下文......但是,您的答案对我有价值,也希望对其他人有用。 –

1

什么是这样的:

强制执行AddressHouse

modelBuilder.Entity<House>().HasRequired(d => d.Address); 

要创建UserAddress之间的一个一对多的关系:

modelBuilder.Entity<User>().HasMany(u => u.Addresses).WithMany().Map(x => 
{ 
    x.MapLeftKey("UserId"); 
    x.MapRightKey("AddressId"); 
    x.ToTable("UserAddress"); 
}); 

什么这应该做的是创建一个名为UserAddress的表,该表将UserAddress

或者,你可以为UserAddress创建POCO自己和修改有关的表格:

public class UserAddress 
{ 
    [Key] 
    public int UserAddressId { get; set; } 
    public User User { get; set; } 
    public Address Address { get; set; } 
} 

public User 
{ 
    ... 
    public virtual ICollection<UserAddress> UserAddresses { get; set; } 
    ... 
} 

public Address 
{ 
    ... 
    public virtual ICollection<UserAddress> UserAddresses { get; set; } 
    ... 
} 

然后您将必须满足下列条件,以确保两个UserAddress是必需的:

modelBuilder.Entity<UserAddress>().HasRequired(u => u.Address); 
modelBuilder.Entity<UserAddress>().HasRequired(u => u.User); 
相关问题