ORM的一个大核心就是实现表间的关系,总结一下EF的实现方式:
1. 一对多的关系:
public class Lodging { …
public Destination Destination { get; set; } [Timestamp] public byte[] RowVersion { get; set; } }
public class Destination { public int DestinationId { get; set; } [Required] public string Name { get; set; } ... public List<Lodging> Lodgings { get; set; }
}
注意此时外键的建立是可为空的
如果设定如下:
[Required]
public Destination Destination { get; set; }
在Context的OnModelCreating方法中:
modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithOptional(l => l.Destination);
在EntityTypeConfiguration的构造函数中:
HasRequired(l => l.Destination).WithMany(d => d.Lodgings).WillCascadeOnDelete(true);
这里说明一下:Has开头的一系列方法代表着实体主题所拥有的属性的约束,比如在modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithOptional(l => l.Destination);例子中,主题是Destination,里面有属性Lodings,HasMany定义了D里面有List的L。WithOption代表的是Lodging里面对于Destination字段的定义是可为空的,这些映射到数据库字段是否可为空有关。
另外,HasXXX和WithXXX的方法体返回可以理解为是对应Labmbada实体的对象,后面的点定义了对于该对象的操作。
2. 外键关系的声明
public class InternetSpecial { …
[ForeignKey("Accommodation")] public int AccommodationId { get; set; } public Lodging Accommodation { get; set; } }
public class InternetSpecial { …
public Lodging Accommodation { get; set; }
}
HasRequired(i => i.Accommodation).WithMany(l => l.InternetSpecials).HasForeignKey(i => i.AccommodationId);
3.级联删除
1: public class LodgingConfig : EntityTypeConfiguration<Lodging> {
2: public LodgingConfig() {
3: HasRequired(l => l.Destination).WithMany(d => d.Lodgings).WillCascadeOnDelete(true);
4: }
5: }
注意:级联删除是在WithMany返回的对象中设定的。默认的设定是非级联删除,如果想要设定,必须显示声明级联删除(设定true)。
4. Include的使用
var destination = context.Destinations
.Include("Lodgings")
.Single(d => d.DestinationId == destinationId);
var aLodging = destination.Lodgings.FirstOrDefault();
假如说Include没有声明,destination.Lodgings的值将会是null,var aLodging一行将会报错。
关联属性如果希望被连同一起实例化(勤劳而非懒惰的方式),那么好,使用Include函数。
说道Include其实关联到了级联删除,如果希望在逻辑层也一起实现级联删除,就以为你需要将所有的关联信息取出来,即需要Include,这个对于性能是一个挑战,所以需要考虑是否真的需要实现应用逻辑层的级联删除。