Инициализация строго типизированных объектов в LINQ to Entities - PullRequest
11 голосов
/ 17 сентября 2009

У меня есть простой старый объект CLR, который, по сути, является оберткой для двух объектов инфраструктуры сущностей, я делаю это, чтобы передать этот объект-оболочку в строго типизированное представление в инфраструктуре MVC. Мой класс foo wrapper очень прост:

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 поддерживаются только беспараметрические конструкторы и инициализаторы». Мне было интересно, есть ли другой способ достичь этого же результата?

Ответы [ 5 ]

20 голосов
/ 17 сентября 2009

ЕСЛИ вы добавляете конструктор без параметров в 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;
}
12 голосов
/ 06 декабря 2010

Хорошо, но что, если вы хотите, чтобы FooObject и BarObject были доступны только для чтения? Мне кажется немного задом наперед, что они сводят на нет возможность использовать конструктор объекта.

Я вижу, как многие люди нарушают хорошие методы инкапсуляции для использования инициализации объектов в этом сценарии.

6 голосов
/ 21 июня 2011

Почему вы не используете .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;
}

У меня была такая же проблема сегодня. У меня был класс с одним конструктором параметров. Этот конструктор заполнил приватное поле только для чтения, которое возвращалось свойством только с get, а не с набором.

3 голосов
/ 17 сентября 2009

Попробуйте другую инициализацию:

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;
}
...