0

我正在编写一个 ASP.NET MVC 4 Web 应用程序。我DbContext.ValidateEntity用来检查即将添加的实体是否通过了一些检查。检查他们的自定义Name属性是否唯一,或者其他属性是否通过我的自定义逻辑。

不过,我的单元测试发现了一些我没想到的行为。我正在使用存储库模式,并且我有一个全局DbContext变量,我使用它并将其传递到我的存储库函数中,以从数据库中检索 EF 模型实体。

在前面,问题是在内部ValidateEntity,当查看正在添加的实体时,我查询所有预先存在的实体并确保特定字段满足通过我的一些唯一性检查。但是,在我查询的预先存在的项目中,我已经看到正在添加的项目。

因此,例如,如果数据库中不存在实体并且我正在创建第一个实体,ValidateEntity那么如果我查询所有现有实体,我将在其中看到它。

我认为这SaveChanges需要ValidateEntity集合中的所有实体,然后再将它们提交到数据库?

4

3 回答 3

1

您永远不必在数据库中“检查唯一性”。该数据库旨在为您做到这一点。数据库具有可以应用的称为唯一约束的东西,如果您的插入违反了这些约束,则会引发异常。您所要做的就是捕获该异常并处理它。添加一堆代码来完成数据库为您做的事情是多余且缓慢的,更不用说在您发现时容易出错。

于 2013-10-09T05:39:29.273 回答
0

问题最终出在我的DbContext. 不应该是全局的DbContext,因为它根本不是线程安全的。感谢神秘人指出这一点。

于 2013-10-10T14:33:38.537 回答
0

也许您可以使用自定义验证属性而不是使用 ValidateEntity?这是检查值是否为小数的自定义属性的示例:

public class MustBeDecimalAttribute : ValidationAttribute, IClientValidatable
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (Equals(value, null))
                return ValidationResult.Success;

            using (new CultureSubstitution(CultureInfo.InvariantCulture))
            {
                if (string.IsNullOrWhiteSpace(value.ToString()))
                    return ValidationResult.Success;

                return !value.ToString().ToDecimal().HasValue
                           ? new ValidationResult(FormatErrorMessage(validationContext.DisplayName))
                           : ValidationResult.Success;
            }
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
                           {
                               ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                               ValidationType = "mustbedecimal"
                           };

            yield return rule;
        }

但不要实现 IClientValidatable 因为您需要查询数据库。构建属性后,只需将其添加到模型中,如下所示:

[MustBeDecimal]
public decimal? RegularPrice { get; set; }
于 2013-10-09T01:13:27.293 回答