【问题标题】:Function in linq selectlinq 选择中的功能
【发布时间】:2021-01-22 11:02:33
【问题描述】:

我有这个错误:

LINQ to Entities 无法识别方法:GetDebitOuCredit

当我运行这个时:

using (SXEntities db = new SXEntities())
{
    result = from ecriture in db.Ecrits
             join compte in db.Comptes on ecriture.Compte equals compte.Compte1
             join societe in db.Societes on ecriture.Societe equals societe.Societe1                             
             select new EcritDTO
             {
                 LibelleElement = compte.Libelle,
                 LienGED = string.Empty, // WIP
                 Compte = ecriture.Compte,
                 Collectif = ecriture.RacColtif,
                 Date = ecriture.DateC,
                 Journal = ecriture.Journal,
                 Piece = ecriture.Piece,
                 CodeOperation = ecriture.CodeOpe,
                 Libelle = ecriture.Libelle,
                 ReferenceDocument = ecriture.DocuRef,
                 // Error just below
                 Debit = GetDebitOuCredit("Debit", societe.DCMoins, ecriture.MtDeb, ecriture.MtCre),
             };
}

我不能使用这个功能:

public double GetDebitOuCredit(string choix, string dcMoins, double? montantDebit, double? montantCredit)
{
    double debit = 0;
    double credit = 0;
    bool isMontantNegatif = string.IsNullOrEmpty(dcMoins) && dcMoins == "1";

    if(montantDebit != null && montantDebit != 0 && montantCredit != null && montantCredit != 0)
    {
        double difference = (double)montantDebit - (double)montantCredit;

        if(difference < 0 && isMontantNegatif)
        {
            debit = 0;
            credit = Math.Abs(difference);
        }
        else
        {
            debit = difference;
            credit = 0;
        }
    }

    return choix == "Debit" ? debit : credit;
}        

我的问题:如何将我的函数 GetDebitOrCredit 转换为 LINQ 表达式?

【问题讨论】:

  • 返回了多少行?
  • EF LINQ 查询被转换为 SQL。如何将本地函数转换为 SQL?
  • 无论如何,该函数不需要是 LINQ 表达式。它可以很容易地成为EcritDTO 的计算属性,或者在加载对象 之后应用于对象。

标签: c# entity-framework linq expression


【解决方案1】:

其实如果是最终投影,就不用翻译这个函数了。 如果没有,您必须为此使用第三方扩展:

https://github.com/hazzik/DelegateDecompiler

https://github.com/axelheer/nein-linq/

从未尝试过DelegateDecompiler,因此将使用NeinLinq 显示示例

[InjectLambda]
public double GetDebitOuCredit(string choix, string dcMoins, double? montantDebit, double? montantCredit)
{
   _getDebitOuCreditFunc ??= GetDebitOuCredit().Compile();
   return _getDebitOuCreditFunc(choix, dcMoins, montantDebit, montantCredit);
}

static Func<string, string, double?, double?, double> _getDebitOuCreditFunc;

public static Expression<Func<string, string, double?, double?, double>> GetDebitOuCredit()
{
    return (choix, dcMoins, montantDebit, montantCredit) =>
       montantDebit != null && montantDebit != 0 && montantCredit != null && montantCredit != 0) 
       ? ((double)montantDebit < (double)montantCredit) && dcMoins == "1" 
          ? choix == "Debit" ? 0 : (double)montantCredit) - (double)montantDebit
          : choix == "Debit" ? (double)montantDebit - (double)montantCredit) : 0
        : 0;
}

然后您可以在ToInjectable() 调用之后在 LINQ 查询中使用您的函数。

result = from ecriture in db.Ecrits.ToInjectable()
         join compte in db.Comptes on ecriture.Compte equals compte.Compte1
         ...
                             

【讨论】:

    【解决方案2】:

    也许您忘记了实际运行查询,当您尝试对其应用其他操作时,它会在稍后运行。试试

    using (SXEntities db = new SXEntities())
    {
        var q  = from ecriture in db.Ecrits
                 join compte in db.Comptes on ecriture.Compte equals compte.Compte1
                 join societe in db.Societes on ecriture.Societe equals societe.Societe1                             
                 select new EcritDTO
                 {
                     LibelleElement = compte.Libelle,
                     LienGED = string.Empty, // WIP
                     Compte = ecriture.Compte,
                     Collectif = ecriture.RacColtif,
                     Date = ecriture.DateC,
                     Journal = ecriture.Journal,
                     Piece = ecriture.Piece,
                     CodeOperation = ecriture.CodeOpe,
                     Libelle = ecriture.Libelle,
                     ReferenceDocument = ecriture.DocuRef,
                     // Error just below
                     Debit = GetDebitOuCredit("Debit", societe.DCMoins, ecriture.MtDeb, ecriture.MtCre),
                 };
         result = q.ToList();
    }
    

    您还应该能够删除连接并执行以下操作:

    using (SXEntities db = new SXEntities())
    {
        var q  = from ecriture in db.Ecrits      
                 select new EcritDTO
                 {
                     LibelleElement = ecriture.Compte.Libelle,
                     LienGED = string.Empty, // WIP
                     Compte = ecriture.Compte,
                     Collectif = ecriture.RacColtif,
                     Date = ecriture.DateC,
                     Journal = ecriture.Journal,
                     Piece = ecriture.Piece,
                     CodeOperation = ecriture.CodeOpe,
                     Libelle = ecriture.Libelle,
                     ReferenceDocument = ecriture.DocuRef,
                     // Error just below
                     Debit = GetDebitOuCredit("Debit", ecriture.Societe.DCMoins, ecriture.MtDeb, ecriture.MtCre),
                 };
         result = q.ToList();
    }
    

    假设您的模型具有适当的导航属性。

    【讨论】:

    • 我放了 ToList() 但无法执行 GetDebitOuCredit() :LINQ to Entities 无法识别该方法..
    • 什么版本的 EF?
    • 这是第6版
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    相关资源
    最近更新 更多