发布应用程序时实体返回 null
Posted
技术标签:
【中文标题】发布应用程序时实体返回 null【英文标题】:Entity is returning null when application is published 【发布时间】:2015-04-07 09:45:29 【问题描述】:我有一个在 Intranet 上发布的应用程序。当我调试我的应用程序时,它运行顺利。但是当我将我的应用程序和我的 Visual Studio 发布为调试器时,从实体中的检索变为 null
。
对象引用未设置为对象的实例。
从此行(使用已发布版本的应用调试器):
user_mstr vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
我正在使用带有实体框架的 mysql 数据库。请注意,我在同一台 PC 上工作,但版本不同,已发布和未发布。
更新:
这仅在发布时返回null
,而不是在调试器上运行时返回。在调试器上一切正常。
这是连接字符串:
connectionString="metadata=res://*/DataAccess.entityName.csdl|res://*/DataAccess.entityName.ssdl|res://*/DataAccess.entityName.msl;provider=MySql.Data.MySqlClient;provider connection string="server=servername;user id=username;password=password;persistsecurityinfo=True;Convert Zero Datetime=True;database=default_db""
我认为值得一提的是我正在研究 WPF。
【问题讨论】:
你在哪里发布app?这一行中的哪个变量是调试器标记为未设置?数据库连接字符串有变化吗?两个数据库中都存在表吗?我知道你增加了一大笔赏金来吸引注意力,但问题没有答案的原因不是注意力,而是缺乏提供答案所需的信息。由于您提供的信息有限,我们无法为您远程调试。 看一下实体框架生成的sql查询。它将帮助您了解问题所在。 Mysql 数据连接器总是让人头疼。 你可能有多个 web.config 版本,具体取决于调试/发布? 当我以前遇到过这样的问题时,我总是在应用程序中添加跟踪(日志记录)调试来诊断生产环境中发生的事情 - 即 TraceLog.WriteLine("strUserCD Value: " + strUserCD.ToString());等等等等…… 同样的IIS?开发 IIS Express 在您的帐户下运行,IIS 可能以 IUSR 运行,谁可能有权访问 SQL 数据库或连接所需的资源,这取决于您的配置。这是第一个也是唯一一个 SQL 查询,还是您有其他在生产中成功执行的查询? 【参考方案1】:步骤零:更多异常信息!
Here is a fiddle that demonstrates 一种从异常消息中获取更多信息的快速而肮脏的方法。
创建以下方法。它递归地从Exception
及其所有InnerException
子代中收集相关信息。
public string ExceptionDetails(StringBuilder b, Exception e)
if (e != null)
b.AppendLine("\n\n-----");
b.AppendLine("Data:".PadRight(20) + e.Data);
b.AppendLine("Message:".PadRight(20) + e.Message);
b.AppendLine("StackTrace:".PadRight(17) + e.StackTrace);
b.AppendLine("TargetSite:".PadRight(20) + e.TargetSite.ToString());
b.AppendLine("-----");
ExceptionDetails(b, e.InnerException);
return b.ToString();
接下来,将您的代码包装在以下 try-catch 块中。
try
user_mstr vwUser =
ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
catch (Exception e)
var builder = new StringBuilder();
var details = ExceptionDetails(builder, e);
throw new Exception(details);
这将为您提供比一般的NullReferenceException
消息更多的信息。有了更多信息,您可能不再需要步骤。
可能的额外步骤
第一步,什么是null?
您已经知道NullReferenceException 的含义。您正在尝试访问值为 null 的类型的成员。排查需要先判断哪个值为null,然后再判断为什么为null。
Here is a Fiddle that narrows down what is null。从那个 Fiddle 中,您可以看到它要么是 ctx
为空,要么是 List<user_mstr>
中的第一项为空(假设 List
是 DbSet
)。
这是 Fiddle 的代码。
using System;
using System.Collections.Generic;
using System.Linq;
public class user_mstr
public string user_cd;
public class FakeContext
public List<user_mstr> user_mstr;
public class Program
private static string strUserCD = "foo";
private static void FirstUserAsNull()
try
Console.WriteLine("FirstUserAsNull");
FakeContext ctx = new FakeContext();
ctx.user_mstr = new List<user_mstr>() null, new user_mstr(), new user_mstr() ;
user_mstr vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
catch (NullReferenceException e)
Console.WriteLine(e.Message);
catch (ArgumentNullException e)
Console.WriteLine(e.Message);
Console.WriteLine();
private static void UserListAsNull()
try
Console.WriteLine("UserListAsNull");
FakeContext ctx = new FakeContext();
ctx.user_mstr = null;
user_mstr vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
catch (NullReferenceException e)
Console.WriteLine(e.Message);
catch (ArgumentNullException e)
Console.WriteLine(e.Message);
Console.WriteLine();
private static void CtxAsNull()
try
Console.WriteLine("CtxAsNull");
FakeContext ctx = null;
user_mstr vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
catch (NullReferenceException e)
Console.WriteLine(e.Message);
Console.WriteLine();
public static void Main()
CtxAsNull();
UserListAsNull();
FirstUserAsNull();
这是输出。
CtxAsNull
Object reference not set to an instance of an object.
UserListAsNull
Value cannot be null.
Parameter name: source
FirstUserAsNull
Object reference not set to an instance of an object.
第二步:什么是真正的 null?
从第一步,我们知道ctx
或List<user_mstr>
中的第一项为空(其中List
就像DbSet
)。现在我们需要进一步缩小。一种方法是将您的代码更改为:
user_mstr vwUser = null;
if(ctx != null)
vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
如果您仍然收到NullReferenceException
,那么您知道有问题的空值是List<user_mstr>
中的第一项。如果您没有收到该异常,那么您就知道问题是空的ctx
。
第三步,如果ctx
为空。
尝试对连接字符串进行硬编码。这是一种方法。
var providerName = "MySql.Data.MySqlClient";
var builder = new StringBuilder();
builder.Append("server=servername;");
builder.Append("user id=username;");
builder.Append("password=password;");
builder.Append("persistsecurityinfo=True;");
builder.Append("Convert Zero Datetime=True;");
builder.Append("database=default_db");
var providerString = builder.ToString();
var entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Provider = providerName;
entityBuilder.ProviderConnectionString = providerString;
entityBuilder.Metadata = @"res://*/DataAccess.entityName.csdl|
res://*/DataAccess.entityName.ssdl|
res://*/DataAccess.entityName.msl";
using (var conn = new EntityConnection(entityBuilder.ToString()))
conn.Open();
// do something
conn.Close();
问题
您使用的是什么版本的 Entity Framework? dev.mysql.com 站点有单独的章节介绍用于 .NET 开发的 MySQL 连接器:Chapter 9 EF 5 Support 和 Chapter 10 EF 6 Support。
您使用的是哪个版本的 .NET? 检查您的调试和发布是否使用相同的 .NET 版本。您至少需要 4.0 版本。
您的发行版 /bin 是否包含 MySql.Data.Entity.dll? 如果不包含,则将其复制粘贴到那里(如果需要,还可以使用 MySql.Web.dll。)实体框架中的 MySql 存在这些错误。
发布和调试版本是否使用相同的数据库?
您使用的是 app.config 转换吗? 这可能不是这种情况,因为您使用的是 WPF 和 app.config transformations do not come out-of-the-box,就像 web.config 转换一样。
您是否使用 web.config 转换?如果您以 WPF Browser Application 发布,那么 web.config 文件将是合适的,web.config transformations 可以更改连接字符串。
您是否已重新构建(清理然后构建)您的版本?您可能需要进一步手动删除 /bin
和 /obj
,然后再进行下一次构建。
注意事项
正如其他人所提到的,您确实需要更多信息。
Binkes 抛出InnerException
的想法很好。
写入日志会有所帮助。
另见
MySQL with Entity Framework - what am I doing wrong?
Entity Framework Code First + MySQL... NullReferenceException
【讨论】:
这个答案可能会导致真正的答案。谢谢@Shaun Luttin 我现在不能检查这个,因为我正在度假。 @ChristianMark,这是一篇很棒的帖子,但我回答了你的问题,记住你不需要修改现有代码来找出原因。 是的 Raishul,我发现我的版本不兼容。对于我的 PC 本身,我有 5.X 版本,而在我的开发环境中我有 6.X。谢谢肖恩 异常详细信息构建器提供的功能并不比 ToString() 提供的好多少。我从未见过 any 异常在 Data 属性中有 anything。你可以在标准的 ToString() 输出中获得所有其余的内容。【参考方案2】:除了其他好主意。 你说出版。我在复制配置文件的方式上看到了类似的问题。 发布过程是否复制了 .config 或由于发布过程现在需要 WEB.CONFIG 而不是 app.config 文件?
换句话说,新位置中的应用程序不会像您怀疑的那样访问配置文件,也没有找到原始 Db 的连接字符串。
【讨论】:
他正在使用 WPF,因此 web.config 不太适合,除非他在 IIS 中将 WPF 作为浏览器应用程序托管。唔。 msdn.microsoft.com/en-us/library/aa970060%28v=vs.110%29.aspx【参考方案3】:要让任何人真正回答这个问题,您需要提供更多信息,例如堆栈跟踪或实际错误。 NullReferenceException 应该有一个内部异常,这是了解您已发布的应用程序有什么问题的关键。为您的项目添加一个类似Log4net 的日志框架或其他日志框架。如果你这样做,你很可能只通过记录异常来获得底层错误和堆栈跟踪。当发生意外错误时,这也会对您有很大帮助。
您始终可以尝试以下方法以获取有关可能出现问题的更多信息:
将您的代码包装在 try-catch 中并抛出 InnerException
try
vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
catch(Exception ex)
throw ex.InnerException;
检查您发布的连接字符串,这样您就没有 将您的连接字符串修改为某些东西的 transorm 配置 出乎意料。
确保您的 IUSR 和 ApplicationPoolIdentity 具有正确的 权限。
从您的项目中删除您的 bin 和 obj 文件夹,清理 解决方案并重建它。尝试发布 debug 版本并确定 它按预期工作。发布一个 release 版本并确定它 有效。
【讨论】:
【参考方案4】:您可以执行以下任务来弄清楚:
要找出幕后发生的事情,请验证由翻译的查询 实体框架通过实现 free profiler 如何从这里指导: http://4rapiddev.com/mysql/free-mysql-profiler-similar-to-microsoft-sql-server-profiler-logmonitor/
检查 strUserCD 变量的值
在 MySQL 中手动执行返回的查询
如果没有返回行,请更改分配 strUserCD 的逻辑 变量。
发布 Web 应用程序并观察是否返回任何异常。
【讨论】:
以上是关于发布应用程序时实体返回 null的主要内容,如果未能解决你的问题,请参考以下文章
Core.net core 3.1 api 返回实体类数据存在null,导致小程序调用接口也直接显示了null,原来要这样设置才可
OpenJPA - 实例的 id 字段在查询时返回 null