在LINQ查询异常后搜索记录

时间:2013-11-11 15:07:21

标签: c# linq entity-framework

我很困惑为什么会这样。我是LINQ的新手,所以我在这里显然遗漏了一些东西,这可能很容易。我已经找到了关于这个主题的帮助,但我真的不知道该问什么,所以我没有找到真正解决我问题的答案。

这不起作用

执行EntityCommandExecutionException方法时会抛出FirstOrDefault

var query = from band in context.BandsEntitySet
            where band.ID == 12345
            select band;

foreach (var item in query)
{
    string venueName = item.VenueName;

    var venue = context.VenueEntitySet.FirstOrDefault(r => r.Venue.Equals(venueName));

    if(venue != null)
    {
        Debug.WriteLine(item.Name + " is playing in " + venueName + " on the " + item.PlayDate);
        Debug.WriteLine("The address of " + venueName + " is " + venue.Address);
    }
}

此作品

var query = from band in context.BandsEntitySet
                    where band.ID == 12345
                    select band;

var bandList = query.toList();

foreach (var item in bandList)
{
    string venueName = item.VenueName;

    var venue = context.VenueEntitySet.FirstOrDefault(r => r.Venue.Equals(venueName));

    if(venue != null)
    {
        Debug.WriteLine(item.Name + " is playing in " + venueName + " on the " + item.PlayDate);
        Debug.WriteLine("The address of " + venueName + " is " + venue.Address);
    }
}

我的问题很简单:为什么会抛出异常?为什么从查询创建列表允许我使用FirstOrDefault方法?

异常消息: A first chance exception of type 'System.Data.EntityCommandExecutionException' occurred in System.Data.Entity.dll

我猜我认为查询是一个列表是错的?那究竟是什么?

这是堆栈跟踪

A first chance exception of type 'System.Data.EntityCommandExecutionException' occurred in System.Data.Entity.dll
   at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
   at System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
   at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](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 BandManagementProject.AutoUpdate.Dev() in c:\BandManagementProject\AutoUpdate.cs:line 99
   at BandManagementProject.AutoUpdate.Main(String[] args) in c:\BandManagementProject\AutoUpdate.cs:line 41

内部异常

MySql.Data.MySqlClient.MySqlException (0x80004005): There is already an open DataReader associated with this Connection which must be closed first.
   at MySql.Data.MySqlClient.ExceptionInterceptor.Throw(Exception exception)
   at MySql.Data.MySqlClient.MySqlConnection.Throw(Exception ex)
   at MySql.Data.MySqlClient.MySqlCommand.Throw(Exception ex)
   at MySql.Data.MySqlClient.MySqlCommand.CheckState()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.Entity.EFMySqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)

结论 在执行其他查询之前,我没有关闭我的LINQ查询。没意识到我需要那样做。我感谢所有的帮助!

感谢, 贾斯汀

1 个答案:

答案 0 :(得分:2)

第一个查询是使用Linq-To-Entities。 Linq-To-Entities方法构建一个表达式树,在枚举时将其转换为sql。如果你包含一些它无法转换为sql的东西,你会得到一个例外。 ToString()就是一个例子。 LINQ to Entities does not recognize the method 'System.String ToString()'

调用ToList()会使枚举发生。所以sql运行,它不包含任何无法翻译的内容,并且数据被移动到内存中。现在您正在使用Linq-To-Objects,并且可以识别标准C#方法调用

试试这个:

var venue = context.VenueEntitySet.FirstOrDefault(r => r.Venue == venueName))

编辑好的,我们知道现在不是问题 - 但另一个需要考虑的想法是在数据库的一次调用中获取数据。像这样:

        var query = from band in context.BandsEntitySet
                    //not sure the join makes sense. How come every band has a VenueName?
                    //join venue in context.VenueEntitySet 
                    //on band.VenueName equals venue.Name
                    //surely there should be a navigation property
                    from venue in band.Venues //using a navigation property
                    where band.ID == 12345
                    select new { 
                                   BandName = band.Name, 
                                   VenueName = venue.Name, 
                                   PlayDate = venue.PlayDate, 
                                   Address = venue.Address 
                               };

        foreach (var item in query)
        {                
            Debug.WriteLine(item.BandName + " is playing in " 
                           + item.VenueName + " on the " + item.PlayDate);
            Debug.WriteLine("The address of " + item.VenueName + " is " + item.Address);

        }

这也应该避免多个打开的DataReader的问题