c# - "Object reference not set to an instance of an object"- 但没有什么是空的?

标签 c# entity-framework-6 dbcontext

是的,您可能认为; “上帝,另一个?”。

是的,另一个。

"Object reference not set to an instance of an object."

我最近一直在使用 EF6,在开发了一段时间后,我发现需要进行更多的优化。很多都已经重做没有问题,但我似乎无法弄清楚这一点。

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

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;
    }
}

请注意 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;
    }
}

据我所知,这应该翻译成 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
    }

    //...
}

编辑 2

经过更多的调试,我发现创建的查询有些不同。应该是这样;

SELECT `Extent1`.`Name` 
FROM `Names` AS `Extent1` 
WHERE (`Extent1`.`Name` IN ( @gp1,@gp2))

但是,我明白了;

System.Data.Entity.Infrastructure.DbQuery<MyDbContext.Names>

作为实际查询。

堆栈跟踪;

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

最佳答案

在您发布堆栈跟踪后,我发现您使用的是 MySQL,所以我猜您遇到了这个错误:Exception when using IEnumera.Contains(model.property) in Where predicate

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

附言此错误报告来自 Alnedru 的这篇文章:Int[].Contains doesn't work in EF6

关于c# - "Object reference not set to an instance of an object"- 但没有什么是空的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27151028/

相关文章:

c# - 在方法内部生成和处理用户消息?

asp.net-core - 应用程序中断访问 dbcontext、Asp .net 核心 web api 2.0 与 Entity Framework 核心 2.0 数据库第一种方法

c# - 从 DB2 数据库生成 EDMX

mysql - Visual Studio 2012 Entity Framework 没有 MySQL 数据源类型

c# - 如何将 DbContext 注入(inject) ASP.NET Core 中的存储库构造函数

c# - 错误 CS1061 'DbContextOptionsBuilder' 不包含定义 > 'UseSqlServer' 并且没有扩展方法 'UseSqlServer'

c# - 访问服务被拒绝 - Bing 语音识别

c# - 如何从 C# 中的数组中删除范围

c# - Entity Framework 仅包含/选择不同表中的某些属性

c# - TCP 连接的可靠性如何?