【发布时间】:2015-03-24 15:57:23
【问题描述】:
使用下面提到的代码时出现错误:InvalidOperationException:
using (MunimPlusContext context = new MunimPlusContext())
{
var dbGroup = context.GroupSet
.Where(x => x.GroupName.ToLower() == groupName.ToLower())
.SingleOrDefault();
if (dbGroup == null)
return true;
else
return dbGroup.GroupId == group.GroupId;
}
错误提供的详细信息是:
超时。在获得一个之前的超时时间 来自池的连接。这可能是因为所有汇集的 正在使用连接并且已达到最大池大小。
我尝试过的:
-
我使用下面提到的代码行来克服这个错误:
context.Database.Connection.Open();
-
我还使用了 SQL Profiler,它按如下方式触发查询,但我不理解生成的 SQL:
exec sp_executesql N'SELECT TOP (2) [Extent1].[GroupId] AS [GroupId], [Extent1].[GroupName] AS [GroupName], [Extent1].[别名] AS [别名], [Extent1].[ParentId] AS [ParentId], [Extent1].[IsSystemGroup] AS [IsSystemGroup], [Extent1].[NatureOfGroupId] AS [NatureOfGroupId], [Extent1].[EffectId] 作为 [EffectId], [Extent1].[BankDetailsVisibility] AS [BankDetailsVisibility], [Extent1].[CreditLimitsVisibility] AS [CreditLimitsVisibility], [Extent1].[GeneralDetailsVisibility] AS [GeneralDetailsVisibility], [Extent1].[ContactDetailsVisibility] AS [ContactDetailsVisibility], [Extent1].[TaxInformationVisibility] AS [TaxInformationVisibility] FROM [dbo].[Group] AS [Extent1] WHERE ((LOWER([Extent1].[GroupName])) = (LOWER(@p__linq__0))) 或 ((LOWER([Extent1].[GroupName]) 为 NULL) AND (LOWER(@p__linq__0) 为 NULL)) ',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'Primary' 去
当我收到此错误时:
当我尝试使用 FluentValidation 在数据库中检查重复项时,如下所示,我收到此错误:
RuleFor(obj => obj.GroupName).Must(UniqueName)
.WithMessage("Group with same name already exists. Please choose a different Group name");
这是错误来源的方法 UniqueName:
private bool UniqueName(Group group, string groupName)
{
using (MunimPlusContext context = new MunimPlusContext())
{
var dbGroup = context.GroupSet
.Where(x => x.GroupName.ToLower() == groupName.ToLower())
.SingleOrDefault();
if (dbGroup == null)
return true;
else
return dbGroup.GroupId == group.GroupId;
}
}
更新:
这是完整的堆栈跟踪:
在 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection,TaskCompletionSource
1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 重试,DbConnectionOptions userOptions)在 System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection 外部连接,DbConnectionFactory 连接工厂, 任务完成源1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource1 重试)在 System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry) at System.Data.SqlClient.SqlConnection.Open() at MunimPlus.Entities.Group.GroupValidator.UniqueName(Group group, String groupName) in H:\Work\Trial\New\MunimPlus\MunimPlusSolution\MunimPlus.Entities\Group.cs:line 274 at FluentValidation.DefaultValidatorExtensions.<>c__DisplayClass42.b__3(T x, TProperty val, PropertyValidatorContext propertyValidatorContext) 在 c:\Projects\FluentValidation\src\FluentValidation\DefaultValidatorExtensions.cs:line 219 在 FluentValidation.DefaultValidatorExtensions.c__DisplayClass72.<Must>b__6(Object instance, Object property, PropertyValidatorContext propertyValidatorContext) in c:\Projects\FluentValidation\src\FluentValidation\DefaultValidatorExtensions.cs:line 235 at FluentValidation.Validators.PredicateValidator.IsValid(PropertyValidatorContext context) in c:\Projects\FluentValidation\src\FluentValidation\Validators\PredicateValidator.cs:line 37 at FluentValidation.Validators.PropertyValidator.Validate(PropertyValidatorContext context) in c:\Projects\FluentValidation\src\FluentValidation\Validators\PropertyValidator.cs:line 71 at FluentValidation.Internal.PropertyRule.InvokePropertyValidator(ValidationContext context, IPropertyValidator validator, String propertyName) in c:\Projects\FluentValidation\src\FluentValidation\Internal\PropertyRule.cs:line 346 at FluentValidation.Internal.PropertyRule.<Validate>d__10.MoveNext() in c:\Projects\FluentValidation\src\FluentValidation\Internal\PropertyRule.cs:line 234 at System.Linq.Enumerable.<SelectManyIterator>d__142.MoveNext() 在 System.Collections.Generic.List1..ctor(IEnumerable1 个集合)
在 System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at FluentValidation.AbstractValidator1.Validate(ValidationContext1 context) in c:\Projects\FluentValidation\src\FluentValidation\AbstractValidator.cs:line 113 at FluentValidation.AbstractValidator1.Validate(T 实例) c:\Projects\FluentValidation\src\FluentValidation\AbstractValidator.cs:line 94 在 FluentValidation.AbstractValidator1.FluentValidation.IValidator.Validate(Object instance) in c:\Projects\FluentValidation\src\FluentValidation\AbstractValidator.cs:line 55 at Core.Common.Core.EntityBase.Validate() in H:\Work\Trial\New\Core\Core.Common\Core\EntityBase.cs:line 206 at Core.Common.Core.EntityBase..ctor() in H:\Work\Trial\New\Core\Core.Common\Core\EntityBase.cs:line 25 at MunimPlus.Entities.Group..ctor() at lambda_method(Closure , Shaper ) at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func2 构造EntityDelegate, EntityKey entityKey, EntitySet entitySet)
在 lambda_method(Closure, Shaper) 在 System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper 整形器)
更新1:
如果我不使用context.Database.Connection.Open(),则会收到另一个错误消息:
基础提供者未能打开。
但在调用数据库之前,我还有其他一些调用正常。
如果我删除此验证,那么我的项目也可以正常工作。
我还是想在这里显示我的连接字符串:
<connectionStrings>
<add name="MunimPlus"
connectionString="data source=.\SQLEXPRESS;Initial Catalog=Max;Integrated Security=SSPI"
providerName="System.Data.SqlClient" />
</connectionStrings>
更新 2:
对问题有一些提示,但没有解决方案。
我有一个名为 EntityBase 的基类。我所有的实体都继承自 EntityBase。所以我的 Group 类看起来像:
public class Group : EntityBase
{
Fields.....
Properties....
class GroupValidator : AbstractValidator<T>
{
public GroupValidator()
{
RuleFor(obj => obj.GroupName).NotEmpty().WithMessage("Group name cannot be empty.");
RuleFor(obj => obj.GroupName).Must(UniqueName).WithMessage("Group with same name already exists. Please choose a different Group name");
RuleFor(obj => obj.ParentId).NotNull().WithMessage("Please select the group under which this group will appear")
.GreaterThan(0).WithMessage("Please select a valid/existing group name");
}
private bool UniqueName(Group group, string groupName)
{
if (groupName == null)
groupName = "";
using (MunimPlusContext context = new MunimPlusContext())
{
Group dbGroup = context.GroupSet.FirstOrDefault(x => x.GroupName.ToLower() == groupName.ToLower());
if (dbGroup == null)
return true;
else
return dbGroup.GroupId == group.GroupId;
}
}
}
protected override IValidator GetValidator()
{
return new GroupValidator();
}
}
看最后一个方法GetValidator,它是EntityBase类中定义的虚方法的重写版本。
现在,EntityBase 类的一部分看起来像:
public abstract class EntityBase
{
public EntityBase()
{
_Validator = GetValidator();
Validate();
}
protected IValidator _Validator = null;
protected IEnumerable<ValidationFailure> _ValidationErrors = null;
protected virtual IValidator GetValidator()
{
return null;
}
public IEnumerable<ValidationFailure> ValidationErrors
{
get { return _ValidationErrors; }
set { }
}
public void Validate()
{
if (_Validator != null)
{
ValidationResult results = _Validator.Validate(this);
_ValidationErrors = results.Errors;
}
}
public virtual bool IsValid
{
get
{
if (_ValidationErrors != null && _ValidationErrors.Count() > 0)
return false;
else
return true;
}
}
}
现在在 CarValidator 类的 UniqueName 方法行中
Group dbGroup = context.GroupSet.FirstOrDefault(x => x.GroupName.ToLower() == groupName.ToLower());
由于 EntityBase 类,为每个组创建并验证了一个新实例。因此,游标在using(MunimPlusContext context = new MunimPlusContext) 上运行,但永远不会关闭连接,因为它越来越深入地创建新的组实例,因此达到了数据库中的最大连接数。因此我遇到了连接池问题。
当我将 Max Pool Size 增加到 999 时,我收到另一个错误 StackOverFlowException。
重现问题的演示项目:
https://drive.google.com/file/d/0B5WyqSALui0bM252VXdveVVMMzQ/view?usp=sharing
【问题讨论】:
-
GroupSet有多大?将ToLower()放在Where中会导致查询中出现小写,这可能会导致大量性能问题。 -
您可以完全删除
Where。context.GroupSet.SingleOrDefault(x => x.GroupName.ToLower() == groupName.ToLower())您也可以将groupName.ToLower()放在本地。否则每次检查都会调用.ToLower();这是没有意义的。 -
@DionV。 GroupSet 只包含 28 条记录......
-
@diemaus 我已经尝试了您建议的代码,但得到了相同的结果。另外,我已经用 Stack Trace 更新了我的问题。你能看一下吗?
-
@DionV。我已经用堆栈跟踪更新了我的问题。你能检查一下吗?
标签: c# sql-server wpf fluentvalidation