我一整天都在努力让它工作。我学到了很多关于 EF 的 Fluent API 的知识(例如,this 是一篇很棒的文章),但是我没有成功。
我有三个实体:
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; }
}
并尝试了我能想到的
HasMany, HasOptional, WithOptional, WithOptionalDependent
和WithOptionalPrincipial
中的User
和House
的所有组合
protected override void OnModelCreating(DbModelBuilder modelBuilder)
我就是无法让它发挥作用。我想应该很清楚,我想要什么。一个用户可能有多个地址(首先我想强制至少一个,但现在如果用户可以有可选的地址我会很高兴......)而房子只有一个地址 - 这是必需的。如果能把房子的地址级联删除就好了
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"));
}
}
请注意,通常最好自己指定外键字段,这可以让您以后的生活变得更加轻松。 如果你这样做,那么你可以选择重写 House 如下:
public class House
{
public int HouseId { get; set; }
public int AddressId { get; set; }
public virtual Address Address { get; set; }
}
Convention将AddressId和Address联系起来。 如果房屋和地址之间有一对一的映射,您还可以在主键上链接它们:
public class House
{
[ForeignKey("Address")]
public int HouseId { get; set; }
public virtual Address Address { get; set; }
}
您提到您希望强制执行至少一个地址 - 这对于一对多关系是不可能的。 仅当用户只有一个地址时才可以执行此操作,此时您可以在 User 类上添加所需的 AddressId 属性。
另一条评论 - 您在代码中将所有内容都虚拟化了。 您只需将导航属性设为虚拟即可。
为
Address
强制执行
House
:
modelBuilder.Entity<House>().HasRequired(d => d.Address);
要在
User
和
Address
之间创建一对多关系:
modelBuilder.Entity<User>().HasMany(u => u.Addresses).WithMany().Map(x =>
{
x.MapLeftKey("UserId");
x.MapRightKey("AddressId");
x.ToTable("UserAddress");
});
这应该做的是创建一个名为
UserAddress
的表,将
User
映射到
Address
。或者,您可以自己为
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; }
...
}
然后,您将需要以下信息来确保
User
和
Address
都是必需的:
modelBuilder.Entity<UserAddress>().HasRequired(u => u.Address);
modelBuilder.Entity<UserAddress>().HasRequired(u => u.User);
modelBuilder.Entity<Technician>()
.HasOne(t => t.Service)
.WithMany(t => t.Technicians)
.HasForeignKey(t => t.ServiceId)
.OnDelete(DeleteBehavior.Restrict);
}