System.Linq.Expressions с вычисляемым столбцом

В проекте MVC я работаю, у меня есть kendo dropDownList, который вызывает мой сервер Action для выполнения любой операции чтения (включая фильтрацию):

ServiceRequestAssociabili([DataSourceRequest] DataSourceRequest request, int? idServiceRequestOriginale)

Виджет связан с 2 свойствами: IdServiceRequest (значение) и IdServiceRequestDescrizione(текст).

IdServiceRequest - это идентификатор объекта, а IdServiceRequestDescrizione - это вычисляемый столбец, который я определил в классе Partial объекта.

public string IdServiceRequestDescrizione
        {
            get
            {
                if (TipologiaChiamata.IdTipologiaChiamata != (int)Enums.TipologiaChiamata.Automatica)
                {
                    return IdServiceRequest + " " + Note;
                }
                else
                {
                    return IdServiceRequest + " " + Email.EmailOggetto;
                }
            }
        }

Чтобы создать правильный запрос linq для выполнения фильтра, я создал выражение System.Linq.Expression, которое переводит мою сущность в DTO, содержащую 2 строковых свойства:

Expression<Func<ServiceRequest, DTO>> funcError = s => new DTO
            {
                IdServiceRequest = s.IdServiceRequest,
                IdServiceRequestDescrizione = s.IdServiceRequestDescrizione
            };

Затем я использую это выражение для проецирования моего IQueryable:

var srq = _serviceRequestRepository.GetByParametersAsQueryable(idServiceRequestOriginale: idServiceRequestOriginale, senzaTicketAssociato: true).Select(funcError).ToList();            

Когда я материализую запрос с помощью ToList(), возникает следующая ошибка: введите описание изображения здесь

Если я вместо определения IdServiceRequestDescrizione в частичном, я определяю его внутри System.Linq.Expression, не выдается никакой ошибки, и все работает нормально.

Expression<Func<ServiceRequest, DTO>> func = s => new DTO
            {
                IdServiceRequest = s.IdServiceRequest,
                IdServiceRequestDescrizione = s.TipologiaChiamata.IdTipologiaChiamata != (int)EntityModel.Enums.TipologiaChiamata.Automatica ? s.IdServiceRequest + " " + s.Note : s.IdServiceRequest + " " + s.Email.EmailOggetto
            };

Может ли кто-нибудь дать мне профессиональное объяснение этого поведения? Почему я не могу ссылаться на пользовательское свойство в выражении linq?

2 ответа

Решение

Вычисляемый столбец реализован в C#, но EF работает только с моделью базы данных (переводится в / из SQL).

Ваш код должен работать, если вы измените порядок вызовов методов на

.ToList().Select(funcError);

т.е. записи сначала переводятся в объекты сущностей C#, а затем доступны вычисляемые столбцы. (Я обычно использую NHibernate, но проблема та же)

Есть несколько вариантов:

1) Linq.Tranlations Linq.Tranlations

Которые позволяют вам писать такие вещи:

public class Customer
{
  public string FirstName { get; set; }
  public string LastName { get; set; }

  private static readonly CompiledExpression<Customer, string> fullNameExpression
     = DefaultTranslationOf<Customer>.Property(e => e.FullName).Is(e => e.FirstName + " " + e.LastName);

  [NotMapped]
  public string FullName
  {
    get { return fullNameExpression.Evaluate(this); }
  }
}

var customers = ctx.Customers
  .Select(c => new
  {
    FullName = c.FullName
  })
  .WithTranslations();

2) DelegateDecompiler DelegateDecompiler

public class Customer
{
  public string FirstName { get; set; }
  public string LastName { get; set; }

  [NotMapped]
  [Computed]
  public string FullName
  {
    get { return FirstName + " " + LastName; }
  }
}
var customers = ctx.Customers
  .Select(c => new
  {
    FullName = c.FullName
  })
  .Decompile();
Другие вопросы по тегам