Ошибка дерева выражений: невозможно создать постоянное значение типа - PullRequest
2 голосов
/ 28 октября 2011

Вот ошибка: невозможно создать постоянное значение типа 'mvcinfosite.ViewModels.GrpSearchHolder'.В этом контексте поддерживаются только примитивные типы (такие как Int32, String и Guid).

Как я могу устранить эту ошибку.Я делаю небольшой пример, чтобы показать вам мою проблему.В моем реальном проекте MyGrp1, MyGrp2, MyGrp3 заменены на ListBox.Я использую его для фильтрации своих данных.

        public class MyGroupHolder
        {
            public string GrpName { get; set; }
            public List<int ?> ListSelectedGrpDescID { get; set; }
        }


        public ActionResult Index()
        {
            //Database Context
            DBEntities db = EntityFactory.GetEntity();

            //Variables
            List<MyGroupHolder> ListGrpHolder = new List<MyGroupHolder>();

            //Imagine a 3 listbox (MyGrp1,MyGrp2,MyGrp3) 
            //Each listbox contains selected value.
            MyGroupHolder MyGrp1 = new MyGroupHolder();
            MyGrp1.GrpName = "Grp 1 Test";
            MyGrp1.ListSelectedGrpDescID = new List<int?>();
            MyGrp1.ListSelectedGrpDescID.Add(55);


            MyGroupHolder MyGrp2 = new MyGroupHolder();
            MyGrp2.GrpName = "Grp 2 Test";
            MyGrp2.ListSelectedGrpDescID = new List<int?>();
            MyGrp2.ListSelectedGrpDescID.Add(56);


            MyGroupHolder MyGrp3 = new MyGroupHolder();
            MyGrp3.GrpName = "Grp 3 Test";
            MyGrp3.ListSelectedGrpDescID = new List<int?>();
            MyGrp3.ListSelectedGrpDescID.Add(57);

            ListGrpHolder.Add(MyGrp1);
            ListGrpHolder.Add(MyGrp2);
            ListGrpHolder.Add(MyGrp3);

            //Getting a list of Locations base on the Group Filter
            var ListLocation = db.Locations.Where(p => ListGrpHolder.Any(pg => pg.ListSelectedGrpDescID.Count == 0 || p.GroupLocations.Select(sg => sg.GrpDescID).Intersect(pg.ListSelectedGrpDescID).Any())).ToList();


            return View();
        }

Ответы [ 3 ]

1 голос
/ 28 октября 2011

Вы не можете передавать объекты из приложения в запросы linq-to-entity. Вы должны извлечь значения и передать их как условия. Просто начало вашего запроса показывает проблему:

.Where(p => ListGrpHolder.Any(...

Как SQL-сервер, ответственный за выполнение запроса Linq-to-entity, должен знать, что такое ListGrpHolder (оно хранится в памяти вашего приложения) и какое значение оно содержит?

Я не совсем понимаю ваш запрос и то, что он должен делать, но просто вы должны строго различаться между linq-to-entity и linq-to-objects. Первый выполняется на SQL-сервере и позволяет передавать только простые типы для запроса. Второй выполняется в вашем приложении, и вы можете использовать любой объект и конструкцию linq для них, но если вы хотите использовать его с данными с SQL-сервера, вы должны сначала загрузить их все в ваше приложение и выполнить фильтрацию в памяти вашего приложения. сервер.

0 голосов
/ 10 ноября 2011

Я преобразовал запрос, чтобы использовать LINQ вместо методов Lambda. Мне легче читать запросы, когда они написаны в синтаксисе LINQ.

Как db.Location относится к pg.ListSelectedGrpDescID.Count == 0? Что должно db.Location вернуть, если оно равно 0? Я оставил эту часть запроса на данный момент.

Может быть хорошей идеей разбить проблему на шаги при попытке найти решение. Это первый шаг к решению.

Во-первых, мы можем преобразовать идентификаторы ListGrpHolder в другой оператор. Это вернет только значение int и облегчит чтение запроса ListLocation.

var SelectedIds = ListGrpHolder.Select(pg => pg.ListSelectedGrpDescID).SelectMany(i => i);
var ListLocation = (from loc in db.Locations
                    from grp in loc.GroupLocations
                    where SelectedIds.Contains(grp.GrpDescID)
                    select loc).ToList();

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

0 голосов
/ 08 ноября 2011

преобразовать ваш запрос, чтобы использовать

из l в db.Locations, где mycalculatedlocalids.Contains (l.id) select l;

IQueryable содержит информацию о поставщике, а IEnumerable (ListGrpHolder) - нет.Вот почему вы не можете выполнить свой запрос на сервере SQL.

...