簡體   English   中英

什么是 function 評估需要所有線程運行?

[英]What is the function evaluation requires all threads to run?

我剛剛制作了一張桌子 Cust 和 Ado.net 並創建了一個 dbEntity 來使用 LINQ

但是我收到了這個錯誤,我無法獲取記錄。

  protected void Page_Load(object sender, EventArgs e)
    {

        SSEntities db = new SSEntities();


        var a = from tb in db.Custs
                select tb;

    }

連接字符串——

    <add name="SSEntities" connectionString="metadata=res://*/DbModel.csdl|res://*/DbModel.ssdl|res://*/DbModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=XYZ\SQLEXPRESS;initial catalog=SS;persist security info=True;user id=sa;password=La123;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

錯誤 - function 評估需要所有線程運行

但這有效

     protected void Page_Load(object sender, EventArgs e)
    {

        SSEntities db = new SSEntities();


        var a = db.Custs.FirstOrDefault();

    }

您必須了解 LINQ 使用的延遲執行。

假設db.Custs是一個 object 實現IQueryable<Cust>或類似的東西。

如果您在第一個示例中檢查a的類型,您會看到它是一個IQueryable<Cust> 第二個示例中的一個是Cust

如果您檢查 LINQ 方法,您會注意到它們有兩組:返回IEnumerable<TResult> (或IQueryable<TResult> )的一組和不返回的一組。

Select, Join, GroupBy是第一組的示例。 他們不執行查詢。 它們不代表獲取的數據,它們代表select 數據的潛力並枚舉它。

只要您只連接該組中的函數。 不查詢您的數據來源。 這個來源通常是一個數據庫,但它可以是任何可枚舉的、CSV 文件閱讀器、JSON 文件、來自互聯網的信息。 在 LINQ 術語中,我們說這些方法使用延遲執行。 您可以在該方法的每個描述中找到該術語。

第二組方法的示例是ToList, FirstOrDefault, Count, Any :返回不是IQueryable<...> 執行其中一個方法將開始枚舉作為輸入源的 IEnumerable/IQueryable:將獲取第一個元素,如果有,並且如果方法需要,將獲取序列的其他元素。

回到你的問題

您的第一個頁面加載將創建查詢。 創造了從數據庫中獲取數據的潛力。 唉,你忘了執行查詢。 如果您調試程序,並在斷點處停止所有線程,並希望檢查 a 的值,您希望查看 object a的屬性。 唉,你的調試器願意向你展示簡單屬性的結果,但是聯系數據庫對它來說太難了。

因此,如果您真的想在調試時查看數據庫查詢的結果,則必須通過添加第二組的方法來執行查詢。 大多數情況下,人們會臨時添加ToList()

在第二個示例中,您使用了第二組的方法:執行查詢,並將結果放入本地 memory:調試器可以訪問數據,因為它只需要檢查一些 memory。

因此,調試解決方案很簡單:在檢查之前添加ToList

改進

現在,您知道第一個示例中的變量a表示獲取數據的可能性,而不是獲取的數據本身。 您顯然簡化了問題的代碼,您想對數據做一些事情。

  • 我很確定 SSEntities 實現了IDisposable 您應該在不再需要它時立即將其丟棄。
  • 確保在處置 SSEntities 之前獲取數據(執行查詢)。

通常人們使用以下結構來確保 object 在所有情況下都正確配置:

using (SSEntities db = new SSEntities())
{
    var myQuery = db.Custs.Select(cust => new {...});

    // execute the query:
    var fetchedData = myQuery.ToList();
}

請注意以下陷阱:

IQueryable<Cust> GetCustomers()
{
    using (SSEntities db = new SSEntities())
    {
        return db.Custs.Select(cust => new {...});
    }
}

查詢未執行,但您已處置 SSEntities。 你的編譯器不會抱怨,你會在運行時得到一個異常。

正確的解決方案是讓您的調用者創建和處理與數據庫的連接,您只需提供選擇:

static IQueryable<Cust> GetCustomersByPostCode(this IQueryable<Cust> customers,
       PostCode postCode)
{
    return customers.Where(customer => customer.PostCode == postCode)
                    .Select(customer => new {...});
}

用法:

protected void Page_Load(object sender, EventArgs e)
{
    List<Customer> customers = null;
    using (SSEntities db = new SSEntities())
    {
    
        PostCode postCode = ...
        customers = db.Customers.GetCustomersByPostCode(postCode).ToList();
    }

    // the database is disposed, cannot be used anymore
    // customers already fetched, can still be used:
    ProcessFetchedCustomers(customers);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM