簡體   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