ASP.NET Core Web API 无法 return 使用 EF Core 延迟加载提取的结果
ASP.NET Core Web API can not return results extracted using EF Core lazy-loading
我正在探索 EF Core 延迟加载,但努力 return 结果优于 ASP.NET Web API。请查看下面我的 API 电话。
// GET: api/Supplier
[HttpGet("/GetSupplierUsingLazyLoading")]
public async Task<ActionResult<Supplier>> GetSupplierUsingLazyLoading()
{
var products = _context.Products.ToList();
var supplier = products.Last().Supplier;
return await Task.FromResult(supplier);
//return await Task.FromResult(new Supplier());
}
是的。我已经添加了包 Microsoft.EntityFrameworkCore.Proxies
并且我在 Startup.cs
中添加了 UseLazyLoadingProxies
services.AddDbContext<NorthwindContext>(
options =>
{
options.UseMySql(Configuration.GetConnectionString("Northwind_MySQL"), Microsoft.EntityFrameworkCore.ServerVersion.Parse("8.0.23-mysql"));
options.UseLazyLoadingProxies();
options.LogTo(Console.WriteLine, LogLevel.Information);
}
);
我正在使用 Pomelo.EntityFrameworkCore.MySql 作为数据库提供程序。
当我从 swagger 调用 Web API 时,它会在幕后进行大量数据库调用。这是我在终端中看到的。它不断地进行这些调用。我不得不停止应用程序来停止这些调用。我不确定我在这里做错了什么。还有其他人面临这个问题吗?
info: 6/26/2021 08:01:55.859 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (1ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.863 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.867 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.870 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.876 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (1ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
当我使用 return await Task.FromResult(new Supplier());
时,它 return 是一个空供应商。
谢谢
好奇的驱动器
首先:请记住,延迟加载是一种仅在需要时从数据库中检索数据的功能,应非常谨慎地使用。
考虑到这一点,让我们谈谈您的模型。
假设您有一个 Supplier
。该供应商必须与一些 Orders
有联系,因为您总是从供应商那里购买东西,对吗?所有 Orders
都有 OrderItems
,并且每个项目都与 Product
相关。所以我们以这样的模型图结束:
你的 类 应该是这样的
public class Supplier
{
public string Name { get; set; }
List<Order> Orders { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
}
public class OrderItem
{
public int OrderItemId { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
public int OrderId { get; set; }
public Order Order { get; set; }
}
public class Order
{
public decimal FinalPrice { get; set; }
public int SupplierId { get; set; }
public Supplier Supplier { get; set; }
List<OrderItem> OrderItems { get; set; }
}
当您尝试序列化来自数据库的 Supplier 时,它也会序列化其 Orders
,然后是 OrderItems
,最后是 Product
,因为您的完整对象图是序列化。
还记得只有在需要时才从数据库中检索数据吗?好吧,序列化器对每个节点进行一次序列化,所以如果您有 4 个订单商品,它将去数据库询问 4 次产品 4 次。
当您序列化一个 new Supplier()
时,这不会发生有两个原因。 new Supplier()
未被 EntityFramework 跟踪,因此不会进行任何查询,即使被跟踪,该供应商也没有订单,因此不会有其他查询 运行.
我正在探索 EF Core 延迟加载,但努力 return 结果优于 ASP.NET Web API。请查看下面我的 API 电话。
// GET: api/Supplier
[HttpGet("/GetSupplierUsingLazyLoading")]
public async Task<ActionResult<Supplier>> GetSupplierUsingLazyLoading()
{
var products = _context.Products.ToList();
var supplier = products.Last().Supplier;
return await Task.FromResult(supplier);
//return await Task.FromResult(new Supplier());
}
是的。我已经添加了包 Microsoft.EntityFrameworkCore.Proxies
并且我在 Startup.cs
UseLazyLoadingProxies
services.AddDbContext<NorthwindContext>(
options =>
{
options.UseMySql(Configuration.GetConnectionString("Northwind_MySQL"), Microsoft.EntityFrameworkCore.ServerVersion.Parse("8.0.23-mysql"));
options.UseLazyLoadingProxies();
options.LogTo(Console.WriteLine, LogLevel.Information);
}
);
我正在使用 Pomelo.EntityFrameworkCore.MySql 作为数据库提供程序。
当我从 swagger 调用 Web API 时,它会在幕后进行大量数据库调用。这是我在终端中看到的。它不断地进行这些调用。我不得不停止应用程序来停止这些调用。我不确定我在这里做错了什么。还有其他人面临这个问题吗?
info: 6/26/2021 08:01:55.859 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (1ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.863 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.867 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.870 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
info: 6/26/2021 08:01:55.876 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (1ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT `o`.`OrderDetailsID`, `o`.`Discount`, `o`.`OrderID`, `o`.`ProductID`, `o`.`Quantity`, `o`.`UnitPrice`
FROM `orderdetails` AS `o`
WHERE `o`.`OrderID` = @__p_0
当我使用 return await Task.FromResult(new Supplier());
时,它 return 是一个空供应商。
谢谢 好奇的驱动器
首先:请记住,延迟加载是一种仅在需要时从数据库中检索数据的功能,应非常谨慎地使用。
考虑到这一点,让我们谈谈您的模型。
假设您有一个 Supplier
。该供应商必须与一些 Orders
有联系,因为您总是从供应商那里购买东西,对吗?所有 Orders
都有 OrderItems
,并且每个项目都与 Product
相关。所以我们以这样的模型图结束:
你的 类 应该是这样的
public class Supplier
{
public string Name { get; set; }
List<Order> Orders { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
}
public class OrderItem
{
public int OrderItemId { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
public int OrderId { get; set; }
public Order Order { get; set; }
}
public class Order
{
public decimal FinalPrice { get; set; }
public int SupplierId { get; set; }
public Supplier Supplier { get; set; }
List<OrderItem> OrderItems { get; set; }
}
当您尝试序列化来自数据库的 Supplier 时,它也会序列化其 Orders
,然后是 OrderItems
,最后是 Product
,因为您的完整对象图是序列化。
还记得只有在需要时才从数据库中检索数据吗?好吧,序列化器对每个节点进行一次序列化,所以如果您有 4 个订单商品,它将去数据库询问 4 次产品 4 次。
当您序列化一个 new Supplier()
时,这不会发生有两个原因。 new Supplier()
未被 EntityFramework 跟踪,因此不会进行任何查询,即使被跟踪,该供应商也没有订单,因此不会有其他查询 运行.