c# – 带有包含的Linq查询仅适用于IQueryable在外部变量中

前端之家收集整理的这篇文章主要介绍了c# – 带有包含的Linq查询仅适用于IQueryable在外部变量中前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用实体框架与 Linq to Entities,尝试从我的数据库中选择一些数据.当我创建一个使用方法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片段中使用此片段中的变量卷.如果我复制此变量的内容并将其粘贴到metrics变量中,导致下面的代码,则会引发错误:“无法创建类型为’CalculadoraRFS.Models.Domain.VolumeAditivo’的常量值.仅原始类型(在这种情况下,支持“如Int32,String和Guid”.“

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;

我如何变量替换导致这样的错误?!我(肯定)做错了吗?
谢谢!

更新:

实际上,我发现Repository Pattern或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.这是一个关于如何 use LINQPad with Entity Framework链接.一个区别可能是使用存储库模式,我没有使用它.我建议使用第一个查询进行测试,以查看生成sql.运行查询后,LINQPad有一个sql选项卡,可以通过查看生成sql来帮助解决正在发生的事情.

如果您仍然遇到组合LINQ语句的问题,那么下一步就是尝试没有Repository对象的Entity Framework对象.如果此查询有效,则可能存在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;

为了找出问题所在,接下来我将使用MetricRepository和VolumeAdditive EF对象.

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;

然后我将它们切换为使用带有VolumeAdditiveRepository的Metric EF对象.

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;

根据这些测试的结果,混合和匹配前面的3个测试/问题,我们应该更接近答案.当我遇到这样的问题时,我试着用可验证的答案问我的自我问题.基本上,我尝试使用科学方法来缩小问题范围以找到解决方案.

猜你在找的C#相关文章