Что вызывает ошибку Linq: этот метод не может быть преобразован в выражение хранилища?

У меня есть куча методов Linq to Entity, у которых был один и тот же оператор select, поэтому я подумал, что был бы умен и разделил это на собственный метод уменьшения избыточности ... но когда я попытался запустить код, я получил следующее ошибка...

этот метод не может быть переведен в выражение магазина

Вот метод, который я создал ...

public User GetUser(DbUser user, long uid)
{
    return new User
    {
        Uid = user.uid,
        FirstName = user.first_name,
        LastName = user.last_name
    };
}

И я вызываю такой метод ...

public User GetUser(long uid)
{
    using (var entities = new myEntities()) {
        return
            entities.DbUsers.Where( x => x.uid == uid && x.account_status == ( short )AccountStatus.Active ).
                Select( x => GetUser( x, uid ) ).FirstOrDefault( );
    }
}

ОБНОВЛЕНИЕ: вот код, который работает inline

public User GetUser(long uid, long uid_user)
        {
            using (var entities = new myEntities())
            {

                var q = from u in entities.DbUsers
                        where u.uid == uid_user
                        select new User
                        {
                            Uid = u.uid,
                            FirstName = u.first_name,
                            LastName = u.last_name,
                            BigPicUrl = u.pic_big,
                            Birthday = u.birthday,
                            SmallPicUrl = u.pic_small,
                            SquarePicUrl = u.pic_square,
                            Locale = u.locale.Trim(),
                            IsFavorite = u.FavoriteFriends1.Any(x => x.uid == uid),
                            FavoriteFriendCount = u.FavoriteFriends.Count,
                            LastWishlistUpdate = u.WishListItems.OrderByDescending(x => x.added).FirstOrDefault().added,
                            Sex = (UserSex)u.sex
                        };

                var user = q.FirstOrDefault();
                user.DaysUntilBirthday = user.Birthday.DaysUntilBirthday();
                return user;
            }
        }

Ответы на вопрос(3)

Ошибка обнаружена, вы не можете перевести это в запрос T-SQL (или P-SQL).

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

Будьте проще, используйте метод расширения. Вот для чего они здесь.

public static User ToUserEntity(this DbUser user)
{
    return new User
    {
        Uid = user.uid,
        FirstName = user.first_name,
        LastName = user.last_name
    };
}

Тогда в вашем DAL:

public User GetUser(long uid)
{
    User dbUser;

    using (var entities = new myEntities())
    {
        dbUser = entities.DbUsers
                  .Where( x => x.uid == uid && x.account_status == (short)AccountStatus.Active )
                 .FirstOrDefault(); // query executed against DB
    }

    return dbUser.ToUserEntity();
}

Посмотрите, как я гидратирую POCO в объектпосле контекст был ликвидирован? Таким образом, вы гарантируете, что EF завершил свою работу над выражениями, прежде чем пытаться гидрировать в пользовательский объект.

Также я не знаю, почему вы передаете uid этому методу, он даже не используется.

С другой стороны, вы не должнынеобходимость чтобы делать такие вещи (проект EF POCO в свои собственные объекты).

Если вы это сделаете, это хороший случай для пользовательских POCO (отобразите таблицы прямо в ваши пользовательские POCO, не используйте генерацию кода).

 RPM198421 сент. 2010 г., 07:36
@wcpro - можете ли вы показать код, где он работает inline? Мне было бы очень интересно посмотреть, как Entity Framework удалось «угадать» отношения между User (случайный объект CLR) и DbUser (объект EF) для создания выражения запроса.
 Rod Johnson21 сент. 2010 г., 07:56
это не дает мне желаемого результата. Мне нужно добавить гораздо больше логики БД в утверждении выбора. пожалуйста, посмотрите обновленный вопрос, вы можете увидеть, где он работает в режиме реального времени. Я пытаюсь написать собственное выражение <> и думаю, что оно будет делать то, что мне нужно.
 RPM198421 сент. 2010 г., 07:52
В любом случае, вы попробовали мой ответ - он должен работать (если у вас нет проблем с перечислением, как Карлос говорит ниже)
 Rod Johnson21 сент. 2010 г., 07:30
ну, я использую uid в фрагменте запроса, который я здесь не показываю (это не повлияло на ошибку). Когда у меня был этот встроенный устав, он работал просто отлично. Но когда я переместить код в свой собственный метод, если не удается. Почему компилятор не может просто подразумевать, что это выражение принадлежит выражению EF. Я знаю, что мог бы увлажнить этот объект впоследствии, но у меня есть несколько полей, которые должны работать в контексте БД. Они просто повторяются снова и снова в строке (и они работали нормально). Я действительно не понимаю, почему вы не можете извлечь эту функциональность в его собственный метод.

Вы не можете сделать это, потому что метод getUser не может быть преобразован в любой оператор TSQL. если вы сначала вернете свой DBUser, а затем используете его в качестве первого параметраGetUser метод, то вы заставляете его выполнить, и как только у вас естьDBUser Вы можете передать этоGetUser

Может быть, вы можете попробовать это:

public User GetUser(long uid)
{
    using (var entities = new myEntities())
    {
        return GetUser(
            entities.DbUsers
                .Where( x => x.uid == uid && x.account_status == (short)AccountStatus.Active )
                .FirstOrDefault(),
            uid);
    }
}

РЕДАКТИРОВАТЬ

Поскольку вы говорите, что он все еще не работает, может ли это быть из-за enum?

public User GetUser(long uid)
{
    using (var entities = new myEntities())
    {
        short status = (short)AccountStatus.Active;
        return GetUser(
            entities.DbUsers
                .Where( x => x.uid == uid && x.account_status == status )
                .FirstOrDefault(),
            uid);
    }
}
 Rod Johnson21 сент. 2010 г., 07:25
EF классы очень грязные, когда вы пытаетесь их сериализовать.
 Rod Johnson21 сент. 2010 г., 07:26
я мог бы сделать это заявление в строке, поэтому я в замешательстве.
 RPM198421 сент. 2010 г., 07:13
Я предполагаю, что DbUser - это EF POCO, а User - его пользовательский бизнес-объект. Тем не менее, я предпочитаю картографирование прямо в моем обычном POCO Оставь среднего человека.
 Rod Johnson21 сент. 2010 г., 06:57
Я попробовал эту технику, и она все еще не работает
 RPM198421 сент. 2010 г., 07:22
После вашего обновления - перечисление может быть проблемой, но это не проблема. EF не имеет возможности преобразовать объект User в запрашиваемое выражение для объекта DbUser.
 Carlos Muñoz21 сент. 2010 г., 07:11
В любом случае, почему у вас есть DbUser и User? Разве EF-объекты не должны быть объектами вашего домена ??? Похоже, что пользователь - это тупая версия DbUser, почему бы просто не работать на DBUsers?

Это выражение будет работать, чтобы дать желаемый результат (в некоторой степени) Я до сих пор не понял, как передать дополнительные переменные в операторах выбора ...

  ..... .Select(GetUser).FirstOrDefault()        

static readonly Expression<Func<DbUser, User>> GetUser = (g) => new User {
            Uid = g.uid,
            FirstName = g.first_name,
            LastName = g.last_name,
            BigPicUrl = g.pic_big,
            Birthday = g.birthday,
            SmallPicUrl = g.pic_small,
            SquarePicUrl = g.pic_square,
            Locale = g.locale.Trim(),
            //IsFavorite = g.FavoriteFriends1.Any(x=>x.uid==uid),
            FavoriteFriendCount = g.FavoriteFriends.Count,
            LastWishlistUpdate = g.WishListItems.OrderByDescending( x=>x.added ).FirstOrDefault().added
        };
 tkerwood13 февр. 2013 г., 04:59
Мне очень нравится это, потому что вы можете использовать его внутри запроса linq до его перечисления, поэтому он работает со списками.

Ваш ответ на вопрос