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標誌。

相關問題