【问题标题】:IN and NOT IN with Linq to Entities (EF4.0)IN 和 NOT IN 与 Linq to Entities (EF4.0)
【发布时间】:2011-03-23 12:09:33
【问题描述】:

这几天已经毁了我的生活,是时候问了...

我正在为我的应用程序使用 Entity Framework 4.0。

一个位置(如房子或办公室)有一个或多个设施(如浴室、卧室、台球桌等)

我想在位置页面上显示一个复选框列表,其中包含设施的复选框列表,其中选中了该位置当前拥有的设施。

我的设施视图模型是这样的......

public class FacilityViewItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool Checked { get; set; }
}

因此,当我将位置视图模型传递给 UI 时,我想传递一个 List<T> 的设施,其中 T 的类型为 FacilityViewItem。

要获得该位置已有的设施很简单——我使用 Location.Facilities 进行查询,它返回一个 EntityCollection,其中 T 是 Facility 类型。这是因为设施是一个导航属性....

var facs = from f in location.Facilities
select new FacilityViewItem()
{
    Id = f.FacilityId,
    Name = f.Name,
    Checked = true
};

所以这就是我的问题所在 - 我想要其余的设施,即 Location 没有的设施。

我尝试过使用 except() 和 Any() 和 Contains(),但我得到了同样的错误。

不起作用的查询示例...

var restOfFacilities = from f in ctx.Facilities
    where !hasFacilities.Contains(f)
    select new FacilityViewItem()
        {
            Id = f.FacilityId,
            Name = f.Name
        };

var restOfFacilities = ctx.Facilities.Except(facilitiesThatLocationHas);

var notFacs = from e in ctx.Facilities
where !hasFacilities.Any(m => m.FacilityId == e.FacilityId)
    select new FacilityViewItem()
        {
            Id = e.FacilityId,
            Name = e.Name
        };

而且我在每次实现时遇到的错误......

System.NotSupportedException 未处理 消息=无法创建类型为“Chapter2ConsoleApp.Facility”的常量值。此上下文仅支持原始类型(“例如 Int32、String 和 Guid”)。

我在这里俯瞰什么?

【问题讨论】:

    标签: linq entity-framework-4 linq-to-entities


    【解决方案1】:

    具有讽刺意味的是,经过几天的痛苦,我在这里发布问题后的几个小时内解决了它。

    错误基本上是说'我不知道如何通过比较强类型对象来计算哪些项目不包括在内。给我一个 Ints 或一些简单类型的列表,我可以处理它。

    所以,首先你需要得到一个主键列表,然后在 contains 子句中使用它...

    //get the primary key ids...
    var hasFacilityIds = from f in hasFacilities
        select f.FacilityId;
    
    //now use them in the contains clause...
    var restOfFacilities = from f in ctx.Facilities
        where !hasFacilityIds.Contains(f.FacilityId)
            select new FacilityViewItem()
                {
                    Id = f.FacilityId,
                    Name = f.Name
                };
    

    【讨论】:

      【解决方案2】:

      第一个查询看起来不错,但是你需要比较Ids:

      var restOfFacilities = from f in ctx.Facilities
                             where !facs.Select(fac => fac.Id).Contains(f.Id)
                             select f;
      

      【讨论】:

      • 这给出了与我已经尝试过的 3 个查询完全相同的错误。
      • ...虽然我对该查询的原始引用中有错误!
      【解决方案3】:

      无论如何,我想看看 hasFacilities 是什么,正如 L2E 所示,“在这种情况下仅支持原始类型('例如 Int32、String 和 Guid')”,所以我想您必须先检索数据并将其放入FacilityViewItem 的集合。

      var restOfFacilities = ctx
          .Facilities
          .Where(f => !hasFacilities.Contains(f))
          .Select(f => new { f.FacilityId, f.Name })
          .ToList()
          .Select(f => new FacilityViewItem {
              Id = f.FacilityId,
              Name = f.Name
          });
      
      var notFacs = ctx
          .Facilities
          .Where(e => !hasFacilities.Any(m => m.FacilityId == e.FacilityId))
          .Select(e => new { e.FacilityId, e.Name })
          .ToList()
          .Select(e => new FacilityViewItem {
              Id = e.FacilityId,
              Name = e.Name
          });
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 2010-09-30
        • 2011-03-04
        • 2010-10-25
        • 2023-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-12
        • 1970-01-01
        相关资源
        最近更新 更多