Инициализация сильно типизированных объектов в LINQ to Entities
У меня есть простой старый объект CLR, который по существу является оберткой для двух объектов фреймворка сущности, я делаю это, поэтому я могу передать этот объект-оболочку строго типизированному представлению в структуре MVC. Мой класс оболочки foo очень прост:
public class FooWrapper
{
public FooWrapper(Foo f, Bar b)
{
this.FooObject = f;
this.BarObject = b;
}
public Foo FooObject { get; private set; }
public Bar BarObject { get; private set; }
}
То, что у меня до сих пор для моей функции ListFoosWithBars, выглядит следующим образом:
public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
{
IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
IEnumerable<FooWrapper> results = (from f in _entities.FooSet
join b in tempBar on f.ID equals b.foos.ID
select new FooWrapper(f, b));
return results;
}
Это не работает, потому что, очевидно, LINQ to Entities не поддерживает параметризованную инициализацию, генерируется исключение, которое говорит только об этом: "В LINQ to Entities поддерживаются только конструкторы без параметров и инициализаторы". Мне было интересно, есть ли другой способ добиться этого же результата?
Ответы
Ответ 1
Если вы добавите конструктор без параметров в свой FooWrapper, а затем используйте инициализацию объекта, например:
public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
{
IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
IEnumerable<FooWrapper> results = (
from f in _entities.FooSet
join b in tempBar on f.ID equals b.foos.ID
select new FooWrapper()
{
FooObject = f,
BarObject = b
});
return results;
}
Ответ 2
Хорошо, но что, если вы хотите, чтобы FooObject и BarObject были только для чтения? Мне кажется немного отсталым, что они отрицают возможность использования конструктора на объекте.
Я вижу, что многие люди нарушают хорошие практики инкапсуляции, чтобы использовать инициализацию объекта в этом сценарии.
Ответ 3
Почему вы не используете .AsEnumerable()? Таким образом, вам не нужно создавать конструктор без параметров и это то, что вы хотите.
Ваш код был почти хорош. Измените его так:
public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
{
IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
IEnumerable<FooWrapper> results = (from f in _entities.FooSet.AsEnumerable()
join b in tempBar on f.ID equals b.foos.ID
select new FooWrapper(f, b));
return results;
}
У меня была такая же проблема сегодня. У меня был класс с одним конструктором параметров. Этот конструктор заполнил частное поле readonly, которое было возвращено свойством только с помощью get, а не с набором.
Ответ 4
Попробуйте выполнить другую инициализацию:
public class FooWrapper
{
public FooWrapper() { }
public Foo FooObject { get; set; }
public Bar BarObject { get; set; }
}
public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
{
IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
IEnumerable<FooWrapper> results = (
from f in _entities.FooSet
join b in tempBar on f.ID equals b.foos.ID
select new FooWrapper
{
FooObject = f,
BarObject = b
});
return results;
}
Ответ 5
Я нашел этот полезный какие возможные обходные пути существуют для "только конструкторы без параметров" - это поддержка в Linq to Entites "