【问题标题】:System.Linq.Expressions with computed columnSystem.Linq.Expressions 与计算列
【发布时间】:2017-04-27 17:31:39
【问题描述】:

在我正在工作的 MVC 项目中,我有一个 kendo dropDownList,它调用我的服务器 Action 来执行任何读取操作(包括过滤):

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

小部件绑定到 2 个属性: IdServiceRequest(值)和 IdServiceRequestDescrizione(文本)。

IdServiceRequest 是实体 ID,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,它将我的实体转换为包含 2 个字符串属性的 DTO:

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 表达式中引用自定义属性?

【问题讨论】:

    标签: c# asp.net-mvc entity-framework linq kendo-asp.net-mvc


    【解决方案1】:

    计算列是用 C# 实现的,但 EF 只对数据库模型进行操作(转换为 SQL 或从 SQL 转换)。

    如果您将方法调用的顺序颠倒过来,您的代码应该可以工作

    .ToList().Select(funcError);
    

    即记录首先被转换为 C# 实体对象,然后计算列可以访问。 (我通常使用NHibernate,但问题是一样的)

    【讨论】:

    • 不是 linq.Expression 也是用 c# 实现的吗?在我的场景中,我无法具体化该指令中的实体,因为额外的过滤器应用于 Iqueryable 对象。明确一点:ToList() 必须在投影到 DTO 之后使用。
    • 这个问题问的基本一样:stackoverflow.com/questions/14726285/…
    【解决方案2】:

    有一些选择:

    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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-11
      • 2018-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多