Entity Framework 在内存数据库提供程序中的奇怪行为
Entity Framework In Memory Database provider weird behavior
[HttpGet]
public JsonResult GetTodoItems()
{
return new JsonResult(_context.TodoItems.ToList());
}
[HttpPost]
public JsonResult PostTodoItem(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();
return new JsonResult("Added successfully!");
}
[HttpDelete("{id}")]
public JsonResult DeleteTodoItem(long id)
{
_context.TodoItems.Remove(_context.TodoItems.Find(id));
_context.SaveChanges();
return new JsonResult("Deleted successfully!");
}
此外,这是 TodoItem 模型:
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
出于某种原因,我不明白以下场景的幕后情况:
我使用 API 删除了其中一项。如果我现在将另一个项目添加到列表中,TodoItems 的顺序似乎会改变,并且想知道在幕后发生了什么来调用这种行为。
这是一个例子——这是开始的情况:
[
{ "Id": 1, "Name": "Item1", "IsComplete": false },
{ "Id": 2, "Name": "Item2", "IsComplete": false },
{ "Id": 3, "Name": "Item3", "IsComplete": false }
]
现在我删除了 Item2 然后 API 返回的列表是:
[
{ "Id": 1, "Name": "Item1", "IsComplete": false },
{ "Id": 3, "Name": "Item3", "IsComplete": false}
]
然后我添加 Item4 然后列表是:
[
{ "Id": 1, "Name": "Item1", "IsComplete": false },
{ "Id": 4, "Name": "Item4", "IsComplete": false },
{ "Id": 3, "Name": "Item3", "IsComplete": false }
]
如您所见,Item4 已添加到上次删除的项目所在的位置。在此之后,如果我添加后续项目,它会继续在列表末尾添加项目, returns 如此。这可能是因为我猜是 EF 的 InMemory Database Provider,因为它主要用于测试目的。但是尽管如此,我还是想知道这个列表是如何在这种现象背后发挥作用的。
使用本地监视 window 没有帮助,因为它确实从列表中删除了 Item2 对象并且显然移动了列表以添加新项目。
编辑:当我在这里谈论列表如何工作时,我的意思是 DbSet 如何在此添加和删除操作中工作,因为 _context.TodoItems 是一个 DbSet 对象,而 ToList()只是将其转换为列表。
I wanted to know how the list works behind this phenomenon
每个 EF 提供商都会做这样的事情。由此返回的项目顺序:
return new JsonResult(_context.TodoItems.ToList());
是存储提供程序的未记录的实现细节,如果您希望以任何特定顺序返回项目,则必须在 EF 查询中使用 .OrderBy()
。
如果您对 InMemory 提供程序实现感到好奇,代码在 GitHub 上,存储是
private readonly Dictionary<TKey, object?[]> _rows;
https://github.com/dotnet/efcore/blob/main/src/EFCore.InMemory/Storage/Internal/InMemoryTable.cs
这导致:
Remarks
The order of the values in the
Dictionary<TKey,TValue>.ValueCollection is unspecified, but it is the
same order as the associated keys in the
Dictionary<TKey,TValue>.KeyCollection returned by the Keys property.
[HttpGet]
public JsonResult GetTodoItems()
{
return new JsonResult(_context.TodoItems.ToList());
}
[HttpPost]
public JsonResult PostTodoItem(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();
return new JsonResult("Added successfully!");
}
[HttpDelete("{id}")]
public JsonResult DeleteTodoItem(long id)
{
_context.TodoItems.Remove(_context.TodoItems.Find(id));
_context.SaveChanges();
return new JsonResult("Deleted successfully!");
}
此外,这是 TodoItem 模型:
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
出于某种原因,我不明白以下场景的幕后情况:
我使用 API 删除了其中一项。如果我现在将另一个项目添加到列表中,TodoItems 的顺序似乎会改变,并且想知道在幕后发生了什么来调用这种行为。
这是一个例子——这是开始的情况:
[
{ "Id": 1, "Name": "Item1", "IsComplete": false },
{ "Id": 2, "Name": "Item2", "IsComplete": false },
{ "Id": 3, "Name": "Item3", "IsComplete": false }
]
现在我删除了 Item2 然后 API 返回的列表是:
[
{ "Id": 1, "Name": "Item1", "IsComplete": false },
{ "Id": 3, "Name": "Item3", "IsComplete": false}
]
然后我添加 Item4 然后列表是:
[
{ "Id": 1, "Name": "Item1", "IsComplete": false },
{ "Id": 4, "Name": "Item4", "IsComplete": false },
{ "Id": 3, "Name": "Item3", "IsComplete": false }
]
如您所见,Item4 已添加到上次删除的项目所在的位置。在此之后,如果我添加后续项目,它会继续在列表末尾添加项目, returns 如此。这可能是因为我猜是 EF 的 InMemory Database Provider,因为它主要用于测试目的。但是尽管如此,我还是想知道这个列表是如何在这种现象背后发挥作用的。
使用本地监视 window 没有帮助,因为它确实从列表中删除了 Item2 对象并且显然移动了列表以添加新项目。
编辑:当我在这里谈论列表如何工作时,我的意思是 DbSet 如何在此添加和删除操作中工作,因为 _context.TodoItems 是一个 DbSet 对象,而 ToList()只是将其转换为列表。
I wanted to know how the list works behind this phenomenon
每个 EF 提供商都会做这样的事情。由此返回的项目顺序:
return new JsonResult(_context.TodoItems.ToList());
是存储提供程序的未记录的实现细节,如果您希望以任何特定顺序返回项目,则必须在 EF 查询中使用 .OrderBy()
。
如果您对 InMemory 提供程序实现感到好奇,代码在 GitHub 上,存储是
private readonly Dictionary<TKey, object?[]> _rows;
https://github.com/dotnet/efcore/blob/main/src/EFCore.InMemory/Storage/Internal/InMemoryTable.cs
这导致:
Remarks
The order of the values in the Dictionary<TKey,TValue>.ValueCollection is unspecified, but it is the same order as the associated keys in the Dictionary<TKey,TValue>.KeyCollection returned by the Keys property.