【问题标题】:Entity Framework check for uniqueness before insert实体框架在插入前检查唯一性
【发布时间】:2011-11-01 12:16:07
【问题描述】:

您好,我有一个 Invoice 类型,例如:

public class Invoice : IEntity, IValidatableObject
    {
        public virtual int Id { get; set; }

        [Required(ErrorMessage = "Invoice Number is a required field.")]
        [Display(Name = "Invoice Number:")]
        public virtual string InvoiceNumber { get; set; }

        [Required(ErrorMessage = "Invoice Date is a required field.")]
        [Display(Name = "Invoice Date:")]
        [DataType(DataType.Date)]
        public DateTime? InvoiceDate { get; set; }

        [Required(ErrorMessage = "Organisation is a required field.")]
        [Display(Name = "Organisation:")]
        public int OrganisationId { get; set; }

        [Required(ErrorMessage = "Region is a required field.")]
        [Display(Name = "Region:")]
        public virtual int? AreaId { get; set; }

        [Required(ErrorMessage = "Total (Exc. GST) is a required field.")]
        [Display(Name = "Total (Exc. GST):")]
        public decimal? TotalExcludingGst { get; set; }

        [Required(ErrorMessage = "Total (Inc. GST) is a required field.")]
        [Display(Name = "Total (Inc. GST):")]
        public decimal? TotalIncludingGst { get; set; }
        public virtual string CreatedByUserName { get; set; }
        public virtual DateTime CreatedDateTime { get; set; }
        public virtual string LastModifiedByUserName { get; set; }
        public virtual DateTime? LastModifiedDateTime { get; set; }

        // Navigation properties
        public virtual Area Area { get; set; }
        public virtual Organisation Organisation { get; set; }

        public virtual ICollection<InvoiceLine> InvoiceLines { get; set; }

        #region IValidatableObject Members

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if ((TotalExcludingGst + (TotalExcludingGst * .15m)) != TotalIncludingGst) {
                yield return new ValidationResult("The total (exc. Gst) + Gst does not equal the total (inc. Gst).");
            }
        }

        #endregion

我想要做的是确保在插入更新时 OrgansationInvoiceNumber 的组合是唯一的。

我正在考虑类似的事情:

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
            {
                var repository = new Repository<Invoice>();

                if(!repositoy.CheckUnique(Id)) {
                    yield return new ValidationResult("The combination of Organisation and Invoice number is already in use");
                }
            }

这是不好的做法吗?要在模型中实例化存储库?

有没有更好的办法?

【问题讨论】:

  • 捕获异常并处理它有什么问题?这样,您只需在需要时对数据库进行额外调用。
  • 您希望问题的答案是什么?更好的方法是在存储库中保存之前进行检查。或者只是保存然后处理@Jeremy 建议的异常。
  • 但这会填充 ValidationSummary 吗?
  • 我同意,将 UIX 添加到 DB,然后捕获异常。因为如果值不是唯一的,这不像你做出任何决定,只是抛出一个错误,所以它没有添加任何值来首先检查。

标签: asp.net-mvc entity-framework


【解决方案1】:

您的解决方案在多用户场景中无法正常工作。因为在检查ID 是否存在和保存更改之间,可能会插入另一条具有相同ID 的记录。

您可以在您的桌子上创建一个Unique Constraint。这是确保不创建重复项的安全方法。

当前版本的 EF 不模拟/不支持 Unique Constraints。但是,您可以做的是捕获特定异常并检查错误消息。然后显示错误

try
{
    //updation logic
    context.SaveChanges();
}
catch (System.Data.DataException de)
{
    Exception innerException = de;
    while (innerException.InnerException != null)
    {
        innerException = innerException.InnerException;
    }

    if (innerException.Message.Contains("Unique_constraint_name"))
    {
        ModelState.AddModelError(string.Empty, "Error Message");
        return;
    }

    ModelState.AddModelError(string.Empty, "Error Message");

    return View();
}

如果您使用的是 ASP.NET Web 表单,您可以查看this answer

【讨论】:

  • 谢谢,这似乎是最好的选择。不过,我可以看到 Microsoft 更改了消息文本,这将导致它无法正常工作。如果有某种 UniqueConstraintException 会更好。你的方法现在必须做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多