IN和而不是Linq to Entities(EF4.0)

时间:2011-03-23 12:09:33

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

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

我正在为我的应用程序使用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类型。这是因为Facilities是导航属性....

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

所以这就是我的问题所在 - 我想要其他设施,那就是位置没有的设施。

我尝试过使用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未处理   Message =无法创建类型为“Chapter2ConsoleApp.Facility”的常量值。在此上下文中仅支持原始类型(例如Int32,String和Guid')。

我在这里俯瞰什么?

3 个答案:

答案 0 :(得分:19)

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

该错误基本上是说“我不知道如何通过比较强类型对象来计算未包含的项目。给我一个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
            };

答案 1 :(得分:7)

第一个查询似乎很好,但您需要比较Id s:

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

答案 2 :(得分:1)

我想看看有什么功能,无论如何,正如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
    });

希望有所帮助