1

底线在前面

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

问题

我正在开发一个 ASP.NET MVC3 站点,该站点通过使用实体框架的数据访问层访问数据。我有一个 SearchList 实体,它与 Search 实体有多对多的关系。一个 SearchList 可能有多个 Search,一个 Search 可能属于多个 SearchList。

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

SearchLists 可以变得非常大,作为测试,我们创建了一个包含 21,000 次搜索的列表。花了几秒钟,返回的数据大约是 9.5 MB,这是我们预期的,但是 jQueryUI 在尝试对这么多进行表化时感到窒息。

我们想要什么

所以我们想对任何搜索列表可以拥有的搜索数量施加限制。我可以通过应用程序并在其中放置一堆规则来检查集合的大小以及是否尝试添加的搜索加上当前的大小...... yada yada yada。

但是,如果有更好的方法(尤其是可以轻松输出 MVC 会拾取的错误消息的方法),我完全会采用这种方法。

我用谷歌搜索,并仔细阅读了许多 EF 博客,但无济于事。Constrain children and max number of children in collection 和类似搜索返回了关于 Linq 查询以及 Count 和 Max 方法的结果。

任何帮助,将不胜感激。

4

2 回答 2

1

没有内置方法,因此您必须自己编写此类验证代码。一些快速的想法:

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

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

于 2012-06-18T15:59:27.857 回答
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.");
        }
    }

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

于 2012-06-25T20:28:35.117 回答