DbDomainService和IValidatableObject

时间:2013-06-20 10:29:35

标签: entity-framework silverlight wcf-ria-services domainservices

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

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

1 个答案:

答案 0 :(得分: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标志。