簡體   English   中英

EF Count()> 0,但First()引發異常

[英]EF Count() > 0 but First() throws exception

我遇到了一個奇怪的問題。 當用戶訪問我的Web應用程序的任何頁面時,我都會檢查用戶是否有權訪問它,並提供首次試用期。

這是我的代碼:

List<string> temp_workers_id = new List<string>();
...
if (temp_workers_id.Count > 6)
                {
                    System.Data.SqlTypes.SqlDateTime sqlDate = new System.Data.SqlTypes.SqlDateTime(DateTime.Now.Date);    
var rusers = dbctx.tblMappings.Where(tm => temp_workers_id.Any(c => c == tm.ModelID));
    var permissions = dbctx.UserPermissions
       .Where(p => rusers
          .Any(ap => ap.UserID == p.UserID)
             && p.DateStart != null 
             && p.DateEnd != null 
             && p.DateStart <= sqlDate.Value 
             && p.DateEnd >= sqlDate.Value);

    if (permissions.Count() < 1)
    {
       permissions = dbctx.UserPermissions
          .Where(p => rusers
             .Any(ap => ap.UserID == p.UserID) 
                && p.DateStart == null 
                && p.DateEnd == null);

       var used = dbctx.UserPermissions
          .Where(p => rusers
             .Any(ap => ap.UserID == p.UserID) 
                && p.DateStart != null 
                && p.DateEnd != null);

    if (permissions.Count() > 0 && used.Count() < 1)
    {
       var p = permissions.First();
       using (Models.TTTDbContext tdbctx = new Models.TTTDbContext())
       {
              var tp = tdbctx.UserPermissions.SingleOrDefault(tup => tup.UserID == p.UserID);
              tp.DateStart = DateTime.Now.Date;
              tp.DateEnd = DateTime.Now.Date.AddDays(60);
              tdbctx.SaveChanges();
       }

這里的First()方法拋出異常:

序列不包含任何元素

那怎么可能呢?

編輯:我不認為用戶打開兩個瀏覽器並同時在此處導航,但是可能是並發問題嗎?

您聲稱您僅在服務器日志中找到了它,而在調試過程中沒有遇到它。 這意味着在這些行之間:

if (permissions.Count() > 0)
{
    var p = permissions.First();

其他一些進程或線程更改了您的數據庫,以使查詢不再與任何文檔匹配。

這是由持有惰性評估資源的permissions引起的,這意味着僅在迭代查詢時才執行查詢( Count()First() )這樣做)。

因此,在Count() ,執行查詢:

SELECT COUNT(*) ... WHERE ...

此時,該行返回一行。 然后在外部修改數據,從而導致下一個查詢(在First() ):

SELECT n1, n2, ... WHERE ...

返回零行,導致First()拋出。

現在,如何解決該問題,取決於您,並且完全取決於您要如何對這種情況進行建模。 這意味着第二個查詢實際上是正確的:在一刻,沒有到的符合查詢條件的更多的行。 您可以實現一次查詢:

permissions = query.Where(...).ToList()

但這意味着您的邏輯將對過時的數據進行操作。 如果您使用FirstOrDefault()也會發生同樣的情況:

var permissionToApply = permissions.FirstOrDefault();
if (permissionToApply != null)
{
    // rest of your logic
}

因此,這基本上是一個輸球的情況。 您總是有可能使用過時的數據,這意味着下一個代碼:

 tdbctx.UserPermissions.SingleOrDefault(tup => tup.UserID == p.UserID);

也會扔。 因此,每次查詢數據庫時,都必須以一種可以處理不再存在的記錄的方式編寫代碼。

暫無
暫無

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

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