IN и NOT IN с Linq to Entities (EF4.0)
Это разрушило мою жизнь в течение нескольких дней, время, чтобы спросить...
Я использую Entity Framework 4.0 для своего приложения.
A Местоположение (например, дом или офис) имеет одно или несколько объектов (например, ванная комната, спальня, стол для снукера и т.д.).
Я хочу отобразить список флажков на странице местоположения с помощью флажка списка объектов, с теми, которые были проверены на наличие в настоящее время местоположения.
Модель My View для объектов выглядит следующим образом:
public class FacilityViewItem
{
public int Id { get; set; }
public string Name { get; set; }
public bool Checked { get; set; }
}
Поэтому, когда я передаю модель представления местоположения в пользовательский интерфейс, я хочу передать 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
};
Итак, вот где моя проблема - я хочу, чтобы остальные объекты, те, которые не имеют Местоположение.
Я попытался использовать 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).
Что я здесь не вижу?
Ответы
Ответ 1
по иронии судьбы я решил это в течение нескольких часов после того, как я разместил вопрос здесь, после нескольких дней страданий.
Ошибка в основном говорит: "Я не знаю, как рассчитать, какие элементы не включены, сравнивая сильно типизированные объекты. Дайте мне список интов или некоторых простых типов, и я могу позаботиться об этом".
Итак, сначала вам нужно получить список первичных ключей, а затем использовать это в предложении 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
Первый запрос кажется прекрасным, но вам нужно сравнить Id
s:
var restOfFacilities = from f in ctx.Facilities
where !facs.Select(fac => fac.Id).Contains(f.Id)
select f;
Ответ 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
});
надеюсь, что это поможет