c#-引用ITVF会引发“在此上下文上开始的第二次操作,而之前的操作尚未完成”
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c#-引用ITVF会引发“在此上下文上开始的第二次操作,而之前的操作尚未完成”,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3799字,纯文字阅读大概需要6分钟。
内容图文
![c#-引用ITVF会引发“在此上下文上开始的第二次操作,而之前的操作尚未完成”](/upload/InfoBanner/zyjiaocheng/669/9d0b5ab41a5d49a4bfd8aeda748f0685.jpg)
我试图在Linq查询中引用内联表值函数(ITVF):
var results = await (
from v in _context.Vehicles
from r in _context.UnitRepairStatus(v.VehicleNumber) <-- ITVF reference
orderby v.VehicleNumber
select new FooViewModel {
ID = v.ID,
VehicleNumber = v.VehicleNumber,
InRepair = Convert.ToBoolean(r.InRepair) <-- ITFV field
}
).ToListAsync();
查询运行时,将生成错误:
InvalidOperationException: A second operation started on this context
before a previous operation completed. Any instance members are not
guaranteed to be thread safe.
附带代码:
System.Linq.AsyncEnumerable.Aggregate_(IAsyncEnumerable source, TAccumulate seed,
Func accumulator, Func resultSelector, CancellationToken cancellationToken)
MyApplication.Controllers.VehiclesController.Foo() in
VehiclesController.cs06001
如果删除ITFV参考,查询将按预期工作
var results = await (
from v in _context.Vehicles
orderby v.VehicleNumber
select new FooViewModel {
ID = v.ID,
VehicleNumber = v.VehicleNumber,
InRepair = False <-- dummy value
}
).ToListAsync();
为什么添加ITVF参考时会发生这种情况?我该如何解决?
码
UnitRepairStatus ITVF:
CREATE FUNCTION dbo.UnitRepairStatus(
@unit_number varchar(18)
)
RETURNS TABLE
AS
RETURN
SELECT h.InRepair
-- connects to a second database on same server
-- shouldn't be an issue, but mentioning it in case it might be
FROM Schema2..Unit u
INNER JOIN Schema2..History h on u.ID = h.UnitID
WHERE u.UnitNumber = @unit_number
UnitRepairStatus模型:
public class UnitRepairStatus
{
public string UnitNumber { get; set; }
public int? InRepair { get; set; }
}
MyDatabaseDbContext DbContext:
public class MyDatabaseDbContext : DbContext
{
public MyDatabaseDbContext(DbContextOptions<MyDatabaseDbContext> options) : base(options) {}
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
modelBuilder.Query<UnitRepairStatus>();
}
public IQueryable<UnitRepairStatus> UnitRepairStatus(string unitNumber) =>
Query<UnitRepairStatus>().FromSql($"SELECT * FROM UnitRepairStatus({unitNumber})");
}
FooViewModel ViewModel:
public class FooViewModel
{
public int ID { get; set; }
public string VehicleNumber { get; set; }
public bool InRepair { get; set; }
}
VehiclesController构造函数:
public VehiclesController(
ILogger<VehiclesController> logger,
MyDatabaseDbContext context
)
{
_logger = logger;
_context = context;
}
VehiclesController Foo方法:
public async Task<IActionResult> Foo()
{
List<FooViewModel> model = null;
try
{
var results = await ( <-- line referenced in error message
from v in _context.Vehicles
from r in _context.UnitRepairStatus(v.VehicleNumber)
orderby v.VehicleNumber
select new FooViewModel {
ID = v.ID,
VehicleNumber = v.VehicleNumber,
InRepair = Convert.ToBoolean(r.InRepair)
}
).ToListAsync();
}
catch (Exception e)
{
_logger.LogError(e.Message);
throw;
}
return View(model);
}
参考:
> Use a Inline Table-Valued Functions with Linq and Entity Framework
解决方法:
对不起,我的错.上一个问题的答案中的技术适用于使用恒定/可变参数调用ITVF,但不适用于与您的情况相关的子查询(以及我的错误示??例).
解决方案是删除ITVF参数并将结果扩展为也包括该列(有效地将其转换为无参数视图):
CREATE FUNCTION dbo.UnitRepairStatus()
RETURNS TABLE
AS
RETURN
SELECT u.UnitNumber, h.InRepair
FROM Schema2.Unit u
INNER JOIN Schema2.History h on u.ID = h.UnitID
同时从上下文方法中删除参数:
public IQueryable<UnitRepairStatus> UnitRepairStatus() =>
Query<UnitRepairStatus>().FromSql("SELECT * FROM UnitRepairStatus()");
并将LINQ查询更改为使用join:
var results = await (
from v in _context.Vehicles
join r in _context.UnitRepairStatus() on v.VehicleNumber equals r.UnitNumber // <---
orderby v.VehicleNumber
select new FooViewModel {
ID = v.ID,
VehicleNumber = v.VehicleNumber,
InRepair = Convert.ToBoolean(r.InRepair)
}
).ToListAsync();
现在,它应该转换并执行服务器端,并在客户端成功实现.
原始方法的问题在于,EF Core默默地将查询执行切换为客户端评估(讨厌),然后达到在一个上下文中执行多个异步操作的保护.
内容总结
以上是互联网集市为您收集整理的c#-引用ITVF会引发“在此上下文上开始的第二次操作,而之前的操作尚未完成”全部内容,希望文章能够帮你解决c#-引用ITVF会引发“在此上下文上开始的第二次操作,而之前的操作尚未完成”所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。