步骤零:更多异常信息!
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