3

我仍然习惯于EF Code First,他花了数年时间与Ruby ORM ActiveRecord合作。 ActiveRecord以前有各种各样的callbacks,比如before_validation和before_save,可以在将对象发送到数据层之前对其进行修改。我想知道在EF Code First对象建模中是否有等效技术。在使用EF Code-First模型保存或验证之前执行逻辑

我知道如何在实例化时设置对象成员,当然,(设置默认值等),但有时您需要在对象生命周期的不同时刻进行干预。

使用稍微人为的例子,说我有联作者和一个连接表播放,相应地创作对象表示:

public class Authoring 
{ 
    public int ID { get; set; } 

    [Required] 
    public int Position { get; set; } 

    [Required] 
    public virtual Play Play { get; set; } 

    [Required] 
    public virtual Author Author { get; set; } 
} 

其中位置代表相关联的所述作者的零索引排序给定播放。 (您可能会有两个作者的单一“南太平洋”游戏:位置为0的“Rodgers”作者和位置为1的“Hammerstein”作者。)

假设我想创建一个方法,在保存创作记录之前,它会检查是否存在与其关联的Play的任何现有作者。如果否,则将位置设置为0.如果是,则会发现设置与该播放关联的最高值的位置并递增1。

我在哪里可以在EF代码的第一个模型层中实现这样的逻辑?而且,在其他情况下,如果在检查验证错误之前想要处理代码中的数据,该怎么办?

基本上,我正在寻找一个相当于上面提到的Rails生命周期钩子,或者至少有一些伪造它的方法。 :)

回答

3

您可以覆盖DbContext.SaveChanges,做修复那里并调用base.SaveChanges()。如果你这样做,你可能想在修复之前调用DetectChanges。顺便说一句。在编程实体框架DbContext书(ISBN 978-1-449-31296-1)第192-194页中讨论了同样的问题。是的,这是在验证的情况下...

3

您可以实施IValidatableObject。这给你一个钩子:

IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 

而且你可以在那里应用你的验证逻辑。

还有SavingChanges事件ObjectContext(您可以从DbContext获得)。

你可以只创建一个自定义IDoStuffOnSave接口,并将其应用到你的实体需要执行上节省一些逻辑(没有什么现成的)

+3

我会劝阻变化的实体验证的几个原因:1)如果你碰巧改变一个相关的实体,它不会被保存之前不处于修改状态因为DetectChanges在验证后不会被再次调用,2)如果您更改已经验证的相关实体,使其无效,则可以在将其保存到数据库时发生异常3)这违反了单一责任原则。对于SavingChanges事件 - 再次,这是验证发生后,所以你可以开枪自己的脚。 – Pawel 2012-03-23 23:36:03