0

我有一个实现IValidatableObject的POCO对象。DbDomainService和IValidatableObject

public class Documentation : IValidatableObject 
{ 
    [Key] 
    public int DocumentationId { get; set; } 

    [ForeignKey("Project")] 
    public int ProjectId { get; set; } 

    public virtual Project Project { get; set; } 

    public string FileGuid { get; set; } 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     return new[] { new ValidationResult("File has not been uploaded", new[] { "FileGuid" }) }; 
    } 

} 

为什么DbContext会在DbDomainService不运行时运行验证?

该测试通过了的DbContext:

[TestMethod, ExpectedException(typeof(DbEntityValidationException))] 
    public void TestDbContext() 
    { 
     SampleDbContext ctx = new SampleDbContext(); 
     var p = new Project() 
     { 
      ProjectName = "UnitTest", 
     }; 
     var d = new Documentation() 
     { 
      FileGuid = "UnitTestDoc", 
     }; 
     p.Documentations = new List<Documentation>(); 
     p.Documentations.Add(d); 
     ctx.Projects.Add(p); 
     ctx.SaveChanges(); 
    } 

虽然这不(无例外抛出):

[TestMethod, ExpectedException(typeof(ValidationException))] 
    public void TestDbDomain() 
    { 
     SampleDomainService svc = new SampleDomainService(); 
     svc.Initialize(ServiceProvider.CreateDomainServiceContext()); 
     var p = new Project() 
     { 
      ProjectName = "UnitTest", 
     }; 
     var d = new Documentation() 
     { 
      FileGuid = "UnitTestDoc", 
      Project = p, 
     }; 
     ChangeSet changeSet = new ChangeSet(
      new [] { 
       new ChangeSetEntry(1, p, null, DomainOperation.Insert), 
       new ChangeSetEntry(2, d, null, DomainOperation.Insert), 
      } 
     ); 
     svc.Submit(changeSet); 
    } 

示例代码here

回答

0

有两个问题与原代码如上所示。

首先,DomainService不会为IValidatableObject验证错误抛出ValidationException。只有DataAnnotation验证抛出ValidationException。因此,要解决的第一件事是在我的测试案例:

[TestMethod] //, ExpectedException(typeof(ValidationException))] 
public void TestDbDomain() 
{ 
    //... setup 

    bool success = svc.Submit(changeSet); 

    bool foundError = (from item in changeSet.ChangeSetEntries 
         where item.HasError 
         from validationError in item.ValidationErrors 
         select validationError).Any(); 

    Assert.IsTrue(foundError); 
} 

其次,从Telerik的JustDecompiler一点帮助(!非常感谢),事实证明DomainServices.ValidateChanges只有工作,如果有一个在类中的一些成员认为已经用验证指令进行了注释。

public class Documentation : IValidatableObject 
{ 
    ... 

    [DataType("File")] 
    public string FileGuid { get; set; } 

    ... 
} 

DataType(“File”)指令不会触发验证机制中的任何验证,但它对于设置标志很有用。

如果你有兴趣的细节,大约有System.DomainServices.Server.ValidationUtilities.ValidateObjectRecursive看看:

private static bool ValidateObjectRecursive(object instance, string memberPath, ValidationContext validationContext, List<ValidationResult> validationResults) 
{ 
    MetaType metaType = MetaType.GetMetaType(instance.GetType()); 
    if (!metaType.RequiresValidation) 
    { 
     return true; 
    } 

    // ... checks for IValidatableObject later 
} 

这显然是一个错误,因为IValidatableObject的存在应该已经建立metaType.RequiresValidation标志。

相关问题