繁体   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