簡體   English   中英

我可以利用 List<t> 使用 UpdateRange(IEnumerable) 時的函數 Remove(T) 和 Insert(Int32, T)<t> )?</t></t>

[英]Can I take advantage of List<T> functions Remove(T) and Insert(Int32, T) when using UpdateRange(IEnumerable<T>)?

我正在嘗試實現 controller 方法來重新排序需要使用 EF Core 保存在數據庫中的圖像索引。

我有以下 controller 方法:

[HttpPost]
public async Task<JsonResult> ReorderImage(int p_iImageID, int p_iNewOrderIndex)
{
     if (p_iImageID <= 0)
          return Json(new { Status = "Error", Message = $"Unable to retrieve item image with ID of {p_iImageID}" });

     ItemImage l_oItemImage = await _Context.ItemImages.FirstOrDefaultAsync(l_oImage => l_oImage.ID == p_iImageID);

     if (l_oItemImage.IsNull())
          return Json(new { Status = "Error", Message = $"Unable to retrieve item image with ID of {p_iImageID}" });


     List<ItemImage> l_oItemImages = await _Context.ItemImages.Where(l_oImage => l_oImage.ItemID == l_oItemImage.ItemID)
                                                              .OrderBy(l_oImage => l_oImage.Order)
                                                              .ToListAsync();

     l_oItemImages.Remove(l_oItemImage);
     l_oItemImages.Insert(p_iNewOrderIndex, l_oItemImage);

     foreach(ItemImage l_oImage in l_oItemImages)
     {
          l_oImage.Order = l_oItemImages.IndexOf(l_oImage);

          if (l_oItemImages.IndexOf(l_oImage) == 0)
               l_oImage.IsPrimary = true;
          else
               l_oImage.IsPrimary = false;

          l_oImage.Uri = _AzureBlobStorage.GetBlobUri(_ItemImageAzureBlobContainerName, l_oImage.GetFileName());
     }

     _Context.ItemImages.UpdateRange(l_oItemImages);
     await _Context.SaveChangesAsync();

     return Json(l_oItemImages)
}

調用UpdateRange()和隨后的SaveChangesAsync()l_oItemImages的順序和數據對我來說似乎是正確的。

我一直在看這個問題,它提到不創建新類和使用UpdateRange() 這似乎有點不同,但我可以看到這可能是我的問題。

我有這個問題是因為我使用Remove(l_oItemImage)然后Insert(p_iNewOrderIndex, l_oItemImage)操作列表的對象嗎? 還是因為我在抓取項目圖像時使用ToListAsync()開始?

編輯:嘗試用Update(l_oItemImage)代替UpdateRange(l_oItemImages) ,結果相同。 添加了顯示附加實體的 QuickWatch 圖像,兩者均正確顯示State = Modified以及int Orderbool IsPrimary屬性的預期更改值。

DBContext.ChangeTracker.Entries() 的 QuickWatch

編輯 2:添加了 QuickWatch 數據的圖像,並在實體上突出顯示了更改的屬性。

已修改完整實體的 QuickWatch 數據。

是的,您應該能夠利用 List 方法,但是我認為UpdateRange對於這個常見任務來說是不必要的,這是一個替代實現。

您可能需要考慮類似以下內容,而不是為序列實體的子集重新分配序列:

public async Task SetSequenceAsync(int forPageComponentId, int newSequence)
{
    var infoAboutItemWereChangingSequenceFor = await context.PageComponents
        .Where(x => x.Id == forPageComponentId)
        .Select(x => new  { 
            OriginalSequence = x.Sequence, // I need to know it's current sequence.
            x.PageId // I need to only adjust sequences for items that have the same PageId, so I need to know what the pageId is for the item we're targeting.
        }).FirstOrDefaultAsync();

    // Get just the data we want to modify, we're going to include the item we're targeting so this list is inclusive of it.
    // Including the item we're changing to make logic below a little mor consise instead of managing the list and the item we're targeting
    // seperately.
    var allItemsWithSequenceThatWillChange = await context.PageComponents
        .Where(x =>
            x.PageId == infoAboutItemWereChangingSequenceFor.PageId // Only those items sharing the same page Id.
            // Only those items we need to change the sequence for.
            && x.Sequence >= Math.Min(infoAboutItemWereChangingSequenceFor.OriginalSequence, newSequence)
            && x.Sequence <= Math.Max(infoAboutItemWereChangingSequenceFor.OriginalSequence, newSequence)
        )
        .Select(x =>
            new PageComponent() // The type of object EF knows about.
            {
                // The Primary key, so Entity Framework knows what record to change the sequence on.
                Id = x.Id,
                // The sequence value we need to change.
                Sequence = x.Sequence
            }
        ).ToListAsync();

    // Set the sequence of the item we're targeting.
    allItemsWithSequenceThatWillChange
        .Where(x => x.Id == forPageComponentId)
        .First()
        .Sequence = newSequence;

    // Now update the sequence on the other items (excluding the target item)
    foreach (var item in allItemsWithSequenceThatWillChange.Where(x => x.Id != forPageComponentId))
    {
        // Either increment or decrement the sequence depending on how the original item was moved.
        item.Sequence += infoAboutItemWereChangingSequenceFor.OriginalSequence > newSequence ? 1 : -1;
        // Add any other property changes here.
    }

    // Save changes.
    await context.SaveChangesAsync();
}

此外,為了簡化您的 ItemImage object,我注意到您有一個明顯的數據庫持久屬性“IsPrimary” - 您可能希望將其更改為在實體甚至數據庫級別上計算,例如:

public class ItemImage {
    // ... Other Properties ...
    public int Order { get; set; }
    public bool IsPrimary {
        get => Order == 0;
        set {}
    }
}

對於您可以查詢的 MSSQL 數據庫中的計算列,添加到您的 DbContext OnModelCreating:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity(typeof(ImageObject)).Property("IsPrimary").HasComputedColumnSql("CASE WHEN [Order] = 0 THEN 1 ELSE 0 END");
}

暫無
暫無

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

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