存储库 - 打开与此命令关联的DataReader,必须先关闭它

时间:2016-09-25 16:22:27

标签: c# entity-framework repository unit-of-work

我有一个方法来启动使用Entity Framework在MVC中编写的游戏,它已经存储在存储库和工作单元中:

public Team StartTeam(Message message, out string result)
    {
        try
        {
            var player = GetPlayer(message);
            if (player.StatusId == (int)Status.Playing)
            {
                result = Mesages.CantStartGameDuringAnotherGame;
                return null;
            }
            var team = Uow.TeamContext.FindBy(q => q.Name == message.Text).FirstOrDefault();
            if (team == null)
            {
                result = Mesages.UnexpectedError;
                return null;
            }
            var members = Uow.MembershipContext.FindBy(q => q.TeamId == team.Id);
            var players = new List<Player>();
            foreach (var member in members.Where(q => q.PlayerId != player.Id))
            {
                var pl = Uow.PlayerContext.GetSingle(member.PlayerId);
                if (player.StatusId == (int)Status.Active)
                    players.Add(pl);
            }
            players.Add(player);
            player.StatusId = (int)Status.Active;
            if (players.Count < 2)
            {
                result = Mesages.NotEnoughPlayers;
                return null;
            }
            var race = new Race()
            {
                TeamId = team.Id,
                PlayDate = DateTime.Now
            };
            race = Uow.RaceContext.Add(race);
            Uow.Save();
            team.CurrentRaceId = race.Id;
            foreach (var playr in players)
            {
                playr.StatusId =
                    members.First(q => q.PlayerId == playr.Id).StatusId
                        = (int)Status.Playing;
                playr.CurrentTeamId = team.Id;
            }
            result = Mesages.TeamStartedSuccessfuly;
            player.StatusId = (int)Status.Playing;
            return team;
        }
        catch (Exception ex)
        {
            SaveException(ex);
            return null;
        }
    }

每件事情似乎都没问题我可以在我的本地运行但是当我发布它时我给出了这个错误:

There is already an open  DataReader associated with this Command which must be closed first.

这是完整的堆栈跟踪:

    System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.InvalidOperationException: There is already an open  DataReader associated with this Command which must be closed first.
   at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
   at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
   at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)
   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
   at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
   --- End of inner exception stack trace ---
   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
   at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
   at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   at EsmFamilWebHoook.Models.PlayerRepository.GetSingle(Int32 playerId)
   at EsmFamilWebHoook.DatabaseService.StartTeam(Message message, String& result)

发生什么事了? 我看到this post但没有帮助我!

1 个答案:

答案 0 :(得分:0)

可能是您的查询:

var pl = Uow.PlayerContext.GetSingle(member.PlayerId);

放在foreach中,迭代了另一个查询的结果(但是这个查询可能仍然是活动的 - 可能只读取第一批行或者它正在进行一些延迟加载):

foreach (var member in Uow.MembershipContext.FindBy(q => q.TeamId == team.Id).Where(q => q.PlayerId != player.Id))

首先尝试使用.ToArray()强制将第一个查询的结果完全加载到内存中,例如:

foreach (var member in Uow.MembershipContext.FindBy(q => q.TeamId == team.Id).Where(q => q.PlayerId != player.Id).ToArray())

通常,您可以在一段时间内激活1个查询。