我使用代码优先的方法创建了一个简单的一对多层次结构。层次结构中的所有实体都有一个Id(即Guid)以及CreatedOn和LastUpdate的时间戳。这些都包含在BaseEntity类中。每个实体可能有其他属性,但它们对这个问题并不重要。层次结构中的每个实体都有一个指向其父实体的外键,以及子实体的集合。
例如:
public class BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime LastUpdate { get; set; }
}
public class RootDirectory : BaseEntity
{
public string RootName { get; set; }
public ICollection<SubDirectory> SubDirectories { get; set; }
}
子目录类如下:
public class Subdirectory : BaseEntity
{
public string SubDirectoryName { get; set; }
public Guid? RootId { get; set; }
public RootDirectory Root { get; set; }
public ICollection<File> Files { get; set; }
}
File类如下所示:
public class File : BaseEntity
{
public string FileName { get; set; }
public Guid? SubDirectoryId { get; set; }
public SubDirectory SubDirectory { get; set; }
}
这产生了我所期望的适当的外键关系。除了LastUpdate,所有操作都在这个系统中工作得很好。
当我在BaseRepo中使用以下泛型方法时,LastUpdate会按预期进行更新:
public virtual int Update(TEntity entity, bool persist = true)
{
Table.Update(entity);
return persist ? SaveChanges() : 0;
}
例如,当我对文件执行此操作时,LastUpdate会按照预期更改为Update调用的时间。但是,当文件更新时,子目录不会额外更新,反过来,根目录也不会更新。
从本质上讲,EF中是否有一种方法可以在子实体更新时使父实体更新?由于缺乏更好的术语,反向级联更新?(级联删除在较高级别删除时删除每个实体的所有子实体,我可以在较低级别更新并更新所有父实体吗?)
请注意,这是通用的是非常重要的,因为我想在其他实体层次结构上使用这个BaseRepo,而不是这个层次结构,这些层次结构可能有不同的级别和其他类似的差异。
我认为这是可能的,因为GitHub和DevOps上的存储库在文件被更改或添加时会这样做。被修改的文件具有Last change,但它的所有父文件夹也是如此,因为它们知道其中的某些内容已更新。
如果有什么不清楚的地方,请告诉我。就像我说的,EF的其他一切都很顺利,这只是一个小问题,我找不到任何文档或帖子,因为大多数人似乎想走另一个方向,在更新父项时更新子项。
2条答案
按热度按时间htrmnn0y1#
这并不像您希望的那样自动化,但我向上下文添加了SavingChanges事件处理程序。处理程序获取添加或更新的实体的列表,并将其传递给处理例程。您可以看到用于父实体中存在UpdatedDateTime属性的情况的特殊代码。我认为您可以通过递归查找父实体来自动化大部分内容。但我只有几个案例,所以包含这些案例的特定代码会更简单。
r6hnlfcb2#
目前似乎没有现成的解决方案来实现这一点,所以现在我在递归更新中实现,我手动查看并更新已更新或添加的实体的所有父项。如果这在路上发生了变化,请随时放置一个新的答案。