限制实体框架中的子实体数量

时间:2012-06-18 15:45:05

标签: asp.net-mvc entity-framework collections constraints

前排底线

是否有一种简洁的方法可以限制可以属于Entity Framework中父级的子实体的数量。我目前正在使用4.3.1。

问题

我正在开发一个ASP.NET MVC3站点,它通过使用Entity Framework的数据访问层访问数据。我有一个SearchList实体,它与Search实体有很多关系。 SearchList可能有很多搜索,搜索可能属于许多搜索列表。

在网站工作流程的某一点上,用户需要选择要在批量搜索中使用的搜索和其他项目。我们希望页面加载整个搜索列表。

SearchLists可以变得非常大,作为测试,我们创建了一个包含21,000次搜索的搜索列表。它花了几秒钟,返回的数据大约是9.5 MB,这是我们所期待的,但是jQueryUI在尝试表格时会窒息。

我们想要什么

因此,我们希望对搜索列表可以拥有的搜索次数施加限制。我可以通过应用程序并在其中放入一系列规则来检查集合的大小,以及是否尝试添加的搜索加上当前的大小... yada yada yada。

然而,如果有更好的方式(特别是可以轻松输出MVC会提取的错误消息的方式),我会完全接受它。

我用谷歌搜索,并仔细阅读了许多EF博客无济于事。在集合和类似搜索中约束子项和最大子项数已返回有关Linq查询和Count和Max方法的结果。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:1)

没有内置方式,所以你必须自己编写这样的验证代码。一些快速的想法:

  • 例如,您可以为导航属性使用自定义集合,当您尝试添加超出阈值的其他搜索时,将触发异常。它很简单,但它要求你加载所有搜索,它会有并发问题,而且它可以在加载搜索列表和从数据库搜索时触发。
  • 您可以覆盖SaveChanges来处理它。您至少必须检查已经与搜索列表相关的搜索量,但您仍然会遇到并发问题(如果其他请求尝试将搜索添加到同一列表但只剩下一个地方,那么两者都可以成功检查并插入相关搜索)
  • 您可以在数据库触发器中处理它 - 同样会出现并发问题

完全避免并发问题需要带有锁定提示的手写查询,以确保只有一个请求可以检查每个搜索列表的搜索次数,并在原子事务中插入新的搜索。

答案 1 :(得分:0)

我最终使用CustomValidationAttribute,并以非常成功的方式实现了它。请参阅下面的实施信息:

在SearchList实体

    [NotMapped]
    public String ValidationMessage { get; set; }
    [CustomValidation(typeof(EntityValidation.EntityValidators), "ValidateSearchCount")]
    public virtual List<Search> Searches { get; set; }

    public static bool Create(ProjectContext db, SearchList searchList)
    {
        try
        {
            db.SearchLists.Add(searchList);
            db.SaveChanges();
            return true;
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    searchList.ValidationMessage += validationError.ErrorMessage;
                }
            }
            return false;
        }
        catch (Exception)
        {
            return false;
        }
    }

EntityValidators类

    public static ValidationResult ValidateSearchCount(List<Search> Searches)
    {
        bool isValid;
        int count = Searches.Count();
        isValid = (count <= 5000 ? true : false);

        if (isValid)
        {
            return ValidationResult.Success;
        }
        else
        {
            return new ValidationResult("A maximum of 5000 searches may be added to a SearchList.");
        }
    }

更新方法上有一个类似的异常块。这样,当调用SaveChanges时,它会尝试验证实体及其子集合,当集合计数大于5000时,验证器将返回一条错误消息,该消息将被捕获到异常处理程序中并存储在本地属性中控制器检查出错的时间。