"对象引用未设置为对象的实例" - 但什么都不为null?

Dio*_* V. 8 c# dbcontext entity-framework-6

是的,你可能会想; "上帝,另一个?"

是的,另一个.

"你调用的对象是空的."

我最近一直在使用EF6,经过一段时间的开发,我发现需要更多的优化.Alot已经重新设计没有问题,但似乎我无法弄清楚这个.

在我的应用程序中,我一直在使用这段伪代码从数据库中获取项目.

DbContext context = new DbContext();

public IEnumerable<string> GetExistingNames(IEnumerable<string> names)
{
    foreach(string name in names)
    {
        string existingName = context.Names.Where(n => n.Name == name).FirstOrDefault();
        if(existingName == null) continue;
        yield return existingName;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这DbContext只是为了澄清.它在需要时被处理掉.

这种方法"有效",但这意味着,如果我有20个名字要查找,我会打到数据库大约20次.哎哟!

因此,我开始寻找实现单个查询的方法.我找到了一种方法,但它并没有真正发挥作用.这是我目前的做法;

public IEnumerable<string> GetExistingNames(ICollection<string> names)
{
    IQueryable<Names> query = context.Names.Where(n => names.Contains(n.Name));
    if(query == null) yield break;
    foreach(var name in query)
    {
        yield return name.Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

据我所知,这应该转化为SELECT ... FROM Names WHERE ... IN (...).但是,我的应用程序一foreach(var name in query)碰到就崩溃了name,引起了恐惧NullReferenceException.但它确实通过if(query == null),这意味着查询不为空.此时,我很困惑.它怎么能不为null,但仍然抛出这个错误?

如果我尝试使用这种方法访问它,我不确定查询是否会被执行.因此,我尝试使用查询创建列表ToList(),但这会在创建列表时引发相同的异常.

好像每次我打电话query,它给了我一个NullReferenceException.但是,它仍然通过if(query == null).所以,我的问题是;

为什么通过测试,但是无法访问?我误解了IQueryable<>吗?如果我误解了它,应该如何正确地完成它?

编辑

我在发布之前已经调试过.我肯定知道;

  • names 不是空的.
  • context 不是空的.

代码调用函数:

//A wrapper for the DbContext. This is only used for some methods
//which require the DbContext
DbContextWrapper wrapper = new DbContextWrapper();

public void ProcessNames(List<string> inputNames)
{
    //...

    foreach(string existingName in wrapper.GetExistingNames(inputNames))
    {
        //Do something with the names
    }

    //...
}
Run Code Online (Sandbox Code Playgroud)

编辑2

经过一些调试后,我发现创建的查询有些不同.应该是;

SELECT `Extent1`.`Name` 
FROM `Names` AS `Extent1` 
WHERE (`Extent1`.`Name` IN ( @gp1,@gp2))
Run Code Online (Sandbox Code Playgroud)

但是,我得到了这个;

System.Data.Entity.Infrastructure.DbQuery<MyDbContext.Names>
Run Code Online (Sandbox Code Playgroud)

作为实际查询.

堆栈跟踪;

at MySql.Data.Entity.SqlGenerator.Visit(DbPropertyExpression expression)
at MySql.Data.Entity.SqlGenerator.Visit(DbInExpression expression)
at System.Data.Entity.Core.Common.CommandTrees.DbInExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at MySql.Data.Entity.SqlGenerator.VisitBinaryExpression(DbExpression left, DbExpression right, String op)
at MySql.Data.Entity.SqlGenerator.Visit(DbAndExpression expression)
at System.Data.Entity.Core.Common.CommandTrees.DbAndExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at MySql.Data.Entity.SelectGenerator.Visit(DbFilterExpression expression)
at System.Data.Entity.Core.Common.CommandTrees.DbFilterExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at MySql.Data.Entity.SqlGenerator.VisitInputExpression(DbExpression e, String name, TypeUsage type)
at MySql.Data.Entity.SelectGenerator.VisitInputExpressionEnsureSelect(DbExpression e, String name, TypeUsage type)
at MySql.Data.Entity.SelectGenerator.Visit(DbProjectExpression expression)
at System.Data.Entity.Core.Common.CommandTrees.DbProjectExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at MySql.Data.Entity.SelectGenerator.GenerateSQL(DbCommandTree tree)
at MySql.Data.MySqlClient.MySqlProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree)
at System.Data.Entity.Core.Common.DbProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.Common.DbProviderServices.CreateCommandDefinition(DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory, DbCommandTree commandTree, DbInterceptionContext interceptionContext, IDbDependencyResolver resolver, BridgeDataReaderFactory bridgeDataReaderFactory, ColumnMapFactory columnMapFactory)
at System.Data.Entity.Core.EntityClient.Internal.EntityProviderServices.CreateCommandDefinition(DbProviderFactory storeProviderFactory, DbCommandTree commandTree, DbInterceptionContext interceptionContext, IDbDependencyResolver resolver)
at System.Data.Entity.Core.EntityClient.Internal.EntityProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.Common.DbProviderServices.CreateCommandDefinition(DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.CreateCommandDefinition(ObjectContext context, DbQueryCommandTree tree)
at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.Prepare(ObjectContext context, DbQueryCommandTree tree, Type elementType, MergeOption mergeOption, Boolean streaming, Span span, IEnumerable`1 compiledQueryParameters, AliasGenerator aliasGenerator)
at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
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.Infrastructure.DefaultExecutionStrategy.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 MyNameSpace.DbContextWrapper.<GetExistingNames>d__1b.MoveNext() in c:~omitted~\DbContextWrapper.cs:line 70
at MyNameSpace.NameProcessor.ProcessNames(List<string> inputNames) in c:~omitted~\NameProcessor.cs:line 60
Run Code Online (Sandbox Code Playgroud)

Ren*_*iuz 4

在您发布 stacktrace 之后,我发现您使用 MySQL,所以我的猜测是您遇到了此错误:Exception when using IEnumera.Contains(model.property) inWhere 谓词

因此,解决方案是确保您拥有 MySQL Connector/NET 6.7.6 / 6.8.4 / 6.9.5 及更高版本。或者尝试使用Any方法而不是Contains.

Ps 这个错误报告来自 Alnedru 的这篇文章:Int[].Contains 在 EF6 中不起作用