代码之家  ›  专栏  ›  技术社区  ›  SNO

实体框架-外键验证

  •  1
  • SNO  · 技术社区  · 7 年前

    有以下特点 TestClass :

    [Table("xyz")]
    public partial class TestClass{
        [Key]
        public int key {get; set;}
        [ForeignKey("key")]
        public virtual ICollection<ExternalClass> externalClasses{get; set;}
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            ... 
        }
    }
    

    我需要如何设置该类以符合我的以下要求:

    • 我想用实体框架单元测试来测试模型
    • 在生产中, externalClasses 不应该保存(应该已经在数据库中)
    • ef必须确保每个外部类都存在于db中。如果不是,抛出异常。

    我的第一个想法是将外部对象设置为空,并请求validate方法中的数据库检查是否存在外部键。但是这种方法在单元测试中没有那么好的效果,而且在我看来,在模型中拥有数据库请求也不是那么简单。

    有人知道如何用英孚以干净的方式处理这个问题吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Gert Arnold    7 年前

    IValidatableObject Validate

    validationContext ValidateEntity SaveChanges context.Configuration.ValidateOnSaveEnabled true

    protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
    {
        items.Add("context", this);
        return base.ValidateEntity(entityEntry, items);
    }
    

    var context = (MyContext)validationContext.Items["context"];
    

    var ids = externalClasses.Select(c => c.ID).ToList();
    if (context.ExternalClasses.Any(c => !ids.Contains(c.ID))
    {
        yield return new ValidationResult("Some external classes don't exist", 
            new[] { nameof(externalClasses) });
    }
    

        2
  •  0
  •   SNO    7 年前

    [Table("xyz")]
    public partial class TestClass{
        [Key]
        public int key {get; set;}
        [ForeignKey("key")]
        [Required]
        public virtual ExternalClass externalClass{get; set;}
    
    
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            ... 
        }
    }
    

    ServiceClass

    public void InsertNewRecord(TestClass newClass){
        newClass.externalClass = context.Where(e => e.ID = newClass.externalClass.Id).First();
        context.Add(newClass);
        context.SaveChanges();        
    }
    

    newClass.externalClass 设置为空并在验证后引发错误,原因是 [Required] 注释。这有一个额外的优势,即EF不会试图保存外来对象 externalClass 因为它现在识别出这个条目仍然存在。