繁体   English   中英

发布应用程序时,实体返回null

[英]Entity is returning null when application is published

我有一个在Intranet上发布的应用程序。 当我调试应用程序时,它运行平稳。 但是,当我发布应用程序和Visual Studio作为调试器时,从entity的检索变为null

对象引用未设置为对象的实例。

在这一行(使用发布版本中的应用调试器):

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

我正在使用带有实体框架的MySQL数据库。 请注意,我在同一台PC上工作,但版本不同,但尚未发布。

更新:

仅在发布时返回null ,而在调试器上运行时则不返回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。

步骤零:更多异常信息!

这是一个小提琴,它演示了从异常消息中获取更多信息的快速而肮脏的方法。

创建以下方法。 它递归地从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消息更多的信息。 有了更多的信息,您可能不再需要任何步骤。

可能的额外步骤

第一步,什么是空值?

您已经知道NullReferenceException的含义。 您正在尝试访问其值为null的类型的成员。 要进行故障排除,您需要确定哪个值为空,然后需要确定为什么为空。

这里是一个缩小了是空小提琴 从该小提琴中,您可以看到是ctx为空,或者是List<user_mstr>中的第一项为空(只是假设ListDbSet )。

这是小提琴的代码。

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?

从第一步开始,我们知道ctxList<user_mstr>的第一项为空(其中List就像DbSet )。 现在我们需要进一步缩小范围。 一种方法是将代码更改为此:

user_mstr vwUser = null;
if(ctx != null)
{
    vwUser = ctx.user_mstr.FirstOrDefault(x => x.user_cd == strUserCD);
}

如果仍然收到NullReferenceException ,则您知道有问题的null值是List<user_mstr>的第一项。 如果未收到该异常,则说明问题是null 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();
}

问题

  1. 您正在使用哪个版本的Entity Framework? dev.mysql.com站点具有有关用于.NET开发的MySQL连接器的单独章节: 第9章EF 5支持第10章EF 6支持

  2. 您正在使用什么版本的.NET? 检查调试和发行版是否使用相同的.NET版本。 您至少需要4.0版本。

  3. 您的发行版/ bin是否包含MySql.Data.Entity.dll? 如果没有,则将其复制粘贴到该位置(如果需要,则复制并粘贴到MySql.Web.dll中。)在实体框架中,与MySql一起存在这些错误。

  4. 版本和调试版本是否使用相同的数据库?

  5. 您是否正在使用app.config转换? 可能不是这种情况,因为您使用的是WPF,而app.config转换不会像web.config转换那样直接使用。

  6. 您是否正在使用web.config转换? 如果要作为WPF浏览器应用程序发布 ,则应该使用web.config文件,并且web.config转换可以更改连接字符串。

  7. 您是否已重建(先清理然后再构建)您的发行版? 您可能想走得更远,并在下一次构建之前手动删除/bin/obj

笔记

正如其他人提到的那样,您确实需要更多信息。

  • Binkes抛出InnerException想法是好的。
  • 写入日志会有所帮助。

也可以看看

MySQL与实体框架-我在做什么错?

实体框架代码优先+ MySQL ... NullReferenceException

除了其他好主意。
你说发表。 我已经看到了复制配置文件的方式的类似问题。 发布过程是否复制了.config或由于发布过程而现在需要WEB.CONFIG而不是app.config文件?

换句话说,新位置中的应用不会像您怀疑的那样访问配置文件,也不会找到与原始Db的连接字符串。

为了使任何人都能真正回答这个问题,您需要提供更多信息,例如stacktrace或实际错误。 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具有正确的权限。

  • 从项目中删除binobj文件夹,清理解决方案并重建它。 尝试发布调试版本,并检查其是否按预期工作。 发布发行版本,并检查其是否有效。

您可以执行以下任务来找出:

  1. 要查找幕后发生的情况,请验证由
    实体框架,方法是通过以下指南实施免费的探查器:http: //4rapiddev.com/mysql/free-mysql-profiler-similar-to-microsoft-sql-server-profiler-logmonitor/

  2. 检查strUserCD变量的值

  3. 在MySQL中手动执行返回的查询

  4. 如果未返回任何行,请更改逻辑方式来设置strUserCD
    变量。

  5. 发布Web应用程序,观察是否返回任何异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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