简体   繁体   中英

Entity is returning null when application is published

I have an application which is published on intranet. When I debug my application, it runs smoothly. But when I published my app and my visual studio as debugger, retrieval from entity becomes null .

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

From this line (using app debugger from published version):

user_mstr vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);

I am using MySQL database with entity framework. Please take note that I am working on the same PC but different version, published and not.

Update:

This is returning null only when it is published and not when running on debugger. Everything is OK on debugger.

This is the connection string:

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"" 

I think it is worth mentioning that I am working on WPF.

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

  1. 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 .

  2. 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.

  3. 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.

  4. Are the release and debug builds using the same database?

  5. 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.

  6. 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.

  7. 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

In addition to the other good ideas.
You say published. I have seen similar issues with the way the config file gets copied. Did the publish process copy the .config OR due to publish process now needs a WEB.CONFIG not app.config file ?

In other words the app in it new location isnt accessing the config file as you suspect and isnt finding the connection string to the original Db.

For anyone to actually answer this you need to provide some more information like a stacktrace or the actual error. The NullReferenceException should have an inner exception , and that is the key to know what is wrong in your published application. Add a logging framework like Log4net or another logging framework to your project. If you do this, you will most likely get the underlying error and stacktrace by just logging the exception. This will also help you alot, further down the line when unexpected errors occur.

You can always try the following to get some more information about what might be wrong:

Wrap your code in a try-catch and throw the InnerException

try { 
    vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD); 
}
catch(Exception ex) 
{ 
    throw ex.InnerException; 
}
  • Check your published connectionstring so that you don't have a transorm config that modifies your connectionstring to something unexpected.

  • Make sure that your IUSR and ApplicationPoolIdentity have the right permissions.

  • Remove your bin and obj folders from your project, clean the solution and rebuild it. Try to publish a debug version and se if it's working as expected. Publish a release version and se if it works.

You may perform following tasks to figure out:

  1. To find what is happening behind the scene, verify the query translated by
    entity framework by implemententing free profiler by how to guideline from here : http://4rapiddev.com/mysql/free-mysql-profiler-similar-to-microsoft-sql-server-profiler-logmonitor/

  2. Check the value for strUserCD variable

  3. Execute the returned query manually in MySQL

  4. If no row is being returned please change the logic how you are assinging strUserCD
    variable.

  5. Publish the web application and observe any exception is being returned or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM