Элемент указанного типа не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, элементы сущностей и свойства навигации сущностей.

var result =
    (from bd in context.tblBasicDetails
     from pd in context.tblPersonalDetails.Where(x => x.UserId == bd.UserId).DefaultIfEmpty()
     from opd in context.tblOtherPersonalDetails.Where(x => x.UserId == bd.UserId).DefaultIfEmpty()
     select new clsProfileDate()
     {
         DOB = pd.DOB
     });

foreach (clsProfileDate prod in result)
{
    prod.dtDOB = !string.IsNullOrEmpty(prod.DOB) ? Convert.ToDateTime(prod.DOB) : DateTime.Today;
    int now = int.Parse(DateTime.Today.ToString("yyyyMMdd"));
    int dob = int.Parse(prod.dtDOB.ToString("yyyyMMdd"));
    string dif = (now - dob).ToString();
    string age = "0";
    if (dif.Length > 4)
    age = dif.Substring(0, dif.Length - 4);
    prod.Age = Convert.ToInt32(age);
}

GetFinalResult(result);

protected void GetFinalResult(IQueryable<clsProfileDate> result)
{
    int from;
    bool bfrom = Int32.TryParse(ddlAgeFrom.SelectedValue, out from);
    int to;
    bool bto = Int32.TryParse(ddlAgeTo.SelectedValue, out to);

    result = result.AsQueryable().Where(p => p.Age >= from);
}

Здесь я получаю исключение:

Элемент указанного типа "Возраст" не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, элементы сущностей и свойства навигации сущностей.

Если Age отсутствует в базе данных, это свойство, которое я создал в классе clsProfileDate для вычисления Age из DOB. Любое решение этого?

9 ответов

Решение

Вы не можете использовать свойства, которые не сопоставлены со столбцом базы данных в Where выражение. Вы должны построить выражение на основе сопоставленных свойств, например:

var date = DateTime.Now.AddYears(-from);
result = result.Where(p => date >= p.DOB);
// you don't need `AsQueryable()` here because result is an `IQueryable` anyway

В качестве замены для вашего не отображается Age Свойство, которое вы можете извлечь это выражение в статический метод следующим образом:

public class clsProfileDate
{
    // ...
    public DateTime DOB { get; set; } // property mapped to DB table column

    public static Expression<Func<clsProfileDate, bool>> IsOlderThan(int age)
    {
        var date = DateTime.Now.AddYears(-age);
        return p => date >= p.DOB;
    }
}

И затем используйте это так:

result = result.Where(clsProfileDate.IsOlderThan(from));

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

result = result.ToList().Where(p => date >= p.DOB);

Слаума лучше ответит, но это сработает. Это стоит больше, потому что ToList() выполнит запрос к базе данных и переместит результаты в память.

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

public class Building
{
    public string Description { get; }
}

var query = 
    from building in context.Buildings
    select new
    {
        Desc = building.Description
    };
int count = query.ToList();

Вызов ToList выдаст то же сообщение об ошибке. Это очень тонкая ошибка, которую очень трудно обнаружить.

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

В моем приложении я использую пользовательскийDbModelStore чтобы сгенерированный во время выполнения EDMX сохранялся на диск и загружался с диска при запуске (вместо того, чтобы восстанавливать его с нуля), чтобы сократить время запуска приложения - и из-за ошибки в моем коде я не аннулировал файл EDMX на диске - поэтому Производство использовало старую версию файла EDMX с диска, которая ссылалась на более старую версию типов моего приложения до того, как я переименовал имя типа в сообщении об ошибке исключения.

Это исправлено удалением файла кеша и перезапуском приложения.

Я забыл выбрать столбец (или установить / сопоставить свойство со значением столбца):

IQueryable<SampleTable> queryable = from t in dbcontext.SampleTable
                                    where ...
                                    select new DataModel { Name = t.Name };

призвание queryable.OrderBy("Id") бросит исключение, даже если DataModel имеет свойство Id определены.

Правильный запрос:

IQueryable<SampleTable> queryable = from t in dbcontext.SampleTable
                                    where ...
                                    select new DataModel { Name = t.Name, Id = t.Id };

В этом случае один из самых простых и лучших подходов - сначала list а затем использовать where или же select,

result = result.ToList().where(p => date >= p.DOB);

Расширенный ответ:

Поиск в файле edmxи проверьте, сопоставлено ли поле со столбцом в базе данных:

      <EntitySetMapping Name="MY_TABLE">
    <EntityTypeMapping TypeName="MYMODEL.MY_TABLE">
      <MappingFragment StoreEntitySet="MY_TABLE">
        <ScalarProperty Name="MY_COLUMN" ColumnName="MY_COLUMN_NAME" />
      </MappingFragment>
    </EntityTypeMapping>
  </EntitySetMapping>

У меня была эта проблема, потому что в edmx были изменения, которые мне не нужны, и через git я отбросил слишком много изменений...

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

Для меня у меня была модель, вот так:

public class SessionGroup
{
        public int Id { get; set; }
        public int UserId { get; set; }

        private DateTime beginDate;
        private DateTime? endDate;

        public DateTime BeginDate
        {
            get { return beginDate; }
            set { beginDate = DateTimeHelper.ToUtc(value); }
        }

        public DateTime? EndDate
        {
            get { return endDate; }
            set
            {
                if (value.HasValue)
                    endDate = DateTimeHelper.ToUtc(value.Value);
                else
                    endDate = null;
            }
        }

         public bool IsSessionOpen { get { return EndDate == null; } }
         public bool IsSessionClosed { get { return !IsSessionOpen; } }
}

Позже в своем запросе я пытался сделать что-то вроде:

...
.Where(usr => usr.Sessions.All(s => !s.IsSessionClosed))

Проблема здесь, как вы можете предположить, связана с IsSessionClosed который является авто-свойством и не является фактическим полем базы данных, однако я использовал его, потому что не знал, что он не связан с фактическим столбцом БД.

Проверка Count() до предложения WHERE решила мою проблему. Это дешевле, чем ToList()

if (authUserList != null && _list.Count() > 0)
    _list = _list.Where(l => authUserList.Contains(l.CreateUserId));
Другие вопросы по тегам