【问题标题】:Why is Validator.TryValidateObject slowing down exponentially为什么 Validator.TryValidateObject 呈指数级减速
【发布时间】:2014-09-28 23:04:45
【问题描述】:

我查询远程服务以一次接收一批 100 件产品,并继续执行此操作,直到没有更多批次剩余。我将这 100 种产品重新映射到我自己的产品对象,我希望一次验证并保存到数据库中。如果没有验证,我会记录错误并继续其余的。处理完前 100 个后,我会去获取下一批 100 个。总共大约 5000 个。

在分析我的网站后,我看到的问题是 Validator.TryValidateObject 似乎以指数方式运行的时间越来越长。第一批 1000 用时 10 分钟,第二批 1000 用时 20 分钟,第三批 1000 用时 30 分钟。所以每次似乎要多花 10 分钟。

Product 类有一个伙伴类 ProductValidation,其中包含用于验证的适当数据注释。我调用 product.IsValid()。

    public class Product{
        public bool IsValid()
        {
            return this.IsValid<Product, ProductValidation>();
        }
    }

使用以下代码:

    public static bool IsValid<T, U>(this T obj)
    {
        if (typeof(T) != typeof(U))
        {
            TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(T), typeof(U)), typeof(T));
        }

        var validationContext = new ValidationContext(obj, null, null);
        var validationResults = new List<ValidationResult>();
        //The line below slows everything down. If commented out all is fine
        Validator.TryValidateObject(obj, validationContext, validationResults, true);

        if (validationResults.Count > 0)
            return false;
        else
            return true;
    }

为什么上述情况会呈指数级放缓?就像验证器每次都在重新验证所有对象一样。

【问题讨论】:

  • 尝试为每对类型只调用一次AddProviderTransparent

标签: c# asp.net-mvc validation


【解决方案1】:

您所描述的是二次运行时,其中每单位工作的成本随着完成的工作量线性增加。

我能看到的最可能的解释是AddProviderTransparent 扩展了一个具有线性搜索时间的列表,要么是因为它使用线性搜索,要么是因为存在哈希冲突和通过桶的线性搜索。

如果您为每个工作单元添加一个新的提供者,并为每个单元处理整个提供者列表,那么您将获得二次运行时。

不要在每次调用时扩展提供程序列表,而是仅在所需的提供程序不在列表中时才这样做。您可以使用 HashSet&lt;Pair&lt;Type, Type&gt;&gt; 来记住您已添加的 T, U 对。

【讨论】:

  • 试过了,但恐怕没用,谢谢你的好建议!
猜你喜欢
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多