实体框架:创建与另一个类有多个关系的类



考虑以下类:

public class Kid
{

public int Id { get; set; }
public string FirstName { get; set; } 
public string LastName { get; set; }
public Date Time BirthDate { get; set; }
public ProfilePhoto CurrentProfilePhoto { get; set; }
public virtual ICollection<ProfilePhoto> ProfilePhotos { get; set; }
}
public class ProfilePhoto
{
public int Id { get; set; }
public byte[] PhotoData { get; set; }
public DateTime DateTaken { get; set; }
public DateTime DateUploaded { get; set; }

public int KidID { get; set; }
public Kid Kid { get; set; }
}

每个孩子实体都有多个个人资料照片,但它可能有或没有一个当前的个人资料照片。另一方面,每个ProfilePhoto都与一个孩子相关,并且该孩子的一个ProfilePhoto只能是当前的个人资料照片。如何在EntityFramework 6.4中使用DataAnnotations或FluentAPI(如果可能的话,我更喜欢使用DataAnnotations)来表示这些关系。

您可以使用以下三种方法:

选项1:将CurrentProfilePhotoId属性添加到Kid中,作为CurrentProfilePhoto导航属性的FK。

[ForeignKey("CurrentProfilePhoto")]
public int? CurrentProfilePhotoId { get; set; }
public virtual ProphilePhoto CurrentProfilePhoto { get; set; }

选项2:将CurrentProfilePhoto标记为[NotMapped],并从ProfilePhotos集合中计算客户端:

[NotMapped]
public ProphilePhoto CurrentProfilePhoto
{
get { return ProfilePhotos.OrderByDescending(x => x.DateTaken).FirstOrDefault(); }
}

选项3:从实体中删除CurrentProfilePhoto,并在需要当前照片时依赖于对ViewModel的投影。例如

var kid = context.Kids
.Where(x => x.Id == kidId)
.Select(x => new KidDetailViewModel
{
Id = x.Id,
Name = x.LastName + ", " + x.FirstName,
BirthDate = x.BirthDate,
CurrentProfilePhoto = x.ProfilePhotos
.OrderByDescending(p => p.DateTaken)
.FirstOrDefault()
}).Single();

选项1是相当简单的,然而没有办法显式强制任何照片被CurrentProfilePhotoId引用是那个孩子的照片。它可能会意外地关联到与该Kid ID无关的任何其他记录的照片。当使用这样的引用时,建议您在数据库中设置数据完整性检查作业,以便在CurrentPhotoId引用的照片具有不同的Kid ID时提醒您。

选项2确保当前照片总是与那个孩子相关联,但是你要么需要记住在加载一个孩子时总是渴望加载整个ProfilePhotos集合,否则它会触发该集合的惰性加载以获得当前照片。

选项3是我推荐的习惯投影的方法。这样可以确保只引用那个孩子的照片,并生成一个查询,该查询只提取足够的数据来填充您在特定时间需要的数据。在这个例子中,只有一张照片和必要的细节会从Kid记录中被拉回来。

相关内容

最新更新