Step Zero: More Exception Information!
Here is a fiddle that demonstrates a quick and dirty way to get more information from your exception message.
Create the following method. It recursively gathers relevant information from the Exception
and all of its InnerException
children.
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();
}
Next, wrap your code in the following try-catch block.
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);
}
This will give you more than the generic NullReferenceException
message. With more information, you might not need anymore steps.
Possible Extra Steps
Step One, what is null?
You already know what a NullReferenceException means. You're trying to access a member on a type whose value is null. To troubleshoot, you need to determine which value is null, then you need to determine why it is null.
Here is a Fiddle that narrows down what is null. From that Fiddle, you can see that it's either the ctx
that's null or the first item in the List<user_mstr>
that is null (just pretend that a List
is a DbSet
).
Here's the code from the 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();
}
}
And here is the output.
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.
Step Two: what is really null?
From step one, we know that either the ctx
or the first item in the List<user_mstr>
is null (where the List
is just like a DbSet
). Now we need to narrow further. One way to do that is to change your code to this:
user_mstr vwUser = null;
if(ctx != null)
{
vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
}
If you still receive the NullReferenceException
, then you know that the problematic null value is the first item in the List<user_mstr>
. If you don't receive that exception, then you know that the problem is a null ctx
.
Step Three, if the ctx
is null.
Try hard-coding your connection string. Here is one way to do that.
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();
}
Questions
What version of Entity Framework are you using? The dev.mysql.com site has separate chapters about the MySQL Connector for .NET development: Chapter 9 EF 5 Support and Chapter 10 EF 6 Support.
What version of .NET are you using? Check that you're using the same .NET version for both your debug and release. You'll want at least the 4.0 version.
Does your release /bin contain MySql.Data.Entity.dll? If it doesn't then copy-paste it in there (and MySql.Web.dll if necessary.) There have been bugs along these lines with MySql in the Entity Framework.
Are the release and debug builds using the same database?
Are you using an app.config transformation? This probably isn't the case, because you're using WPF and app.config transformations do not come out-of-the-box like web.config transformations do.
Are you using a web.config transformation? If you're publishing as a WPF Browser Application, then a web.config file would be appropriate, and web.config transformations can change the connection string.
Have you rebuilt (clean then build) your release? You might want to go further and manually delete the /bin
and /obj
before your next build.
Notes
As others have mentioned, you really need more information.
- Binkes ideas of throwing the
InnerException
is good.
- Writing to a log would help.
See Also
MySQL with Entity Framework - what am I doing wrong?
Entity Framework Code First + MySQL... NullReferenceException