Linq查询与Contains只工作与iquerable是在外部变量
本文关键字:外部 iquerable 变量 工作 查询 Contains Linq | 更新日期: 2023-09-27 18:10:40
我正在使用Linq实体实体框架,试图从我的数据库中选择一些数据。当我创建一个使用IQueryable<int>.Contains
方法的Linq查询时,如果我使用外部变量,它只能过滤数据!我来举个例子。
这段代码工作得很好:
var volumes = (from v in work.VolumeAdditiveRepository.All
where v.AdditivesID == AdditivesID
select v.MetricID);
var metrics =
from m in work.MetricRepository.All
where !volumes.Contains(m.ID)
select m;
如果你仔细看,你可以看到我在where
条件中使用了变量volumes
。如果我复制该变量的内容并将其粘贴到metrics
变量中,导致下面的代码,它会引发错误:"Unable to create a constant value of type 'CalculadoraRFS.Models.Domain.VolumeAditivo'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."
.
var metrics =
from m in work.MetricRepository.All
where !(from v in work.VolumeAdditiveRepository.All
where v.AdditivesID == AdditivesID
select v.MetricID).Contains(m.ID)
select m;
变量替换怎么可能导致这样的错误?我(肯定)做错了什么吗?
谢谢你!
更新:
实际上,我发现存储库模式或DbContext似乎是问题所在,正如@jhamm指出的那样。下面的代码段也不起作用:
var query = from m in work._context.Metric
where !(from v in work._context.VolumeAdditive
where v.AdditivesID == AdditivesID
select v.MetricID).Contains(m.ID)
select m;
但是下面的代码片段可以工作。我只是从UnitOfWork类中取出上下文,尽管它在那里定义得非常简单:public CalculadoraRFSContext _context = new CalculadoraRFSContext();
.
var _context = new CalculadoraRFSContext();
var query = from m in _context.Metric
where !(from v in _context.VolumeAdditive
where v.AdditivesID == AdditivesID
select v.MetricID).Contains(m.ID)
select m;
现在我对这些东西真的很困惑!这不应该像预期的那样起作用吗!
我使用LINQPad在类似类型的查询上使用我的EF Database First模型。组合查询和单独查询都给出了相同的正确结果并生成了相同的SQL。这里是如何使用LINQPad与实体框架的链接。其中一个区别可能是使用了存储库模式,我没有使用存储库模式。我建议对第一个查询进行测试,看看生成了什么SQL。在运行查询之后,LINQPad有一个SQL选项卡,可以通过查看生成的SQL来帮助解决问题。
如果你仍然对组合LINQ语句有问题,一个好的下一步将是尝试没有Repository对象的实体框架对象。如果此查询有效,则您的Repository对象可能有问题。
// Guessing that Metric and VolumeAdditive are the EF Entities
// LINQPad database dropdown sets the context so they were not set it in these samples
var metrics =
from m in Metric
where !(from v in VolumeAdditive
where v.AdditivesID == AdditivesID
select v.MetricID).Contains(m.ID)
select m;
为了找出问题所在,我接下来将使用带有VolumeAdditive EF对象的MetricRepository。
var metrics =
from m in work.MetricRepository.All
where !(from v in VolumeAdditive
where v.AdditivesID == AdditivesID
select v.MetricID).Contains(m.ID)
select m;
然后我将它们切换到使用Metric EF对象和VolumeAdditiveRepository。
var metrics =
from m in Metric
where !(from v in work.VolumeAdditiveRepository.All
where v.AdditivesID == AdditivesID
select v.MetricID).Contains(m.ID)
select m;
基于生成的SQL和查询工作,我认为这应该有助于指出你在正确的方向。这是基于移除问题的一部分直到它起作用。然后将它们重新添加,直到它们断裂,以指出问题所在。这些步骤应该使用小的增量更改来完成,以最小化问题空间。
更新:
根据新信息,让我们试着把新信息分成我们需要回答的新问题。
也许LINQ表达式不能弄清楚如何处理where子句中的work._context.VolumeAdditive
。所以让我们用下面的方法来验证这个理论。这将上下文设置为单个变量,而不是使用work._context。
var _context = work._context;
var query = from m in _context.Metric
where !(from v in _context.VolumeAdditive
where v.AdditivesID == AdditivesID
select v.MetricID).Contains(m.ID)
select m;
也许使用let语句来定义MetricID可以解决这个问题。
var metrics =
from m in work.MetricRepository.All
let volumes = from v in work.VolumeAdditiveRepository.All
where v.AdditivesID == AdditivesID
select v.MetricID
where !volumes.Contains(m.ID)
select m;
根据这些测试的结果,并混合和匹配前三个测试/问题,我们应该更接近答案。当我遇到这样的问题时,我试着问自己一些可以证实的答案。基本上,我试着用科学的方法来缩小问题的范围,找到一个解决方案。