C#中Lambda表達式類型Expression不接受lambda函數

在EF Core中咱們常常會用System.Linq.Expressions系統命名空間的Expression<TDelegate>類型來做爲EF Core的查詢條件,好比:git

using EFLambdaExpression.Entities;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace EFLambdaExpression
{
    class Program
    {
        static void Main(string[] args)
        {
            using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
            {
                Expression<Func<User, bool>> userExperssion = u => u.UserCode != null;

                var users = dbContext.User.Where(userExperssion).ToList();
            }

            Console.WriteLine("Press key to quit....");

            Console.ReadLine();
        }
    }
}

可是若是咱們將Expression<Func<User, bool>> userExperssion = u => u.UserCode != null改成Expression<Func<User, bool>> userExperssion = u => { return u.UserCode != null; }那麼C#會報錯,提示:數據庫

A lambda expression with a statement body cannot be converted to an expression tree

因此Expression<Func<User, bool>> userExperssion不能接受帶函數體的u => { return u.UserCode != null; }這種lambda函數,它只支持簡單的lambda表達式u => u.UserCode != nullexpress

 

雖然Expression<Func<User, bool>> userExperssion右邊的lambda表達式中可使用自定義函數,可是不建議這麼作,由於這麼作會致使EF Core對數據庫表作全表查詢函數

好比咱們先執行下面的代碼:ui

using EFLambdaExpression.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace EFLambdaExpression
{
    class Program
    {
        static void Main(string[] args)
        {
            using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
            {
                Expression<Func<User, bool>> userExperssion = u => EF.Functions.Like(u.UserCode, "%ADMIN%");

                var users = dbContext.User.Where(userExperssion).ToList();
            }

            Console.WriteLine("Press key to quit....");

            Console.ReadLine();
        }
    }
}

能夠從EF Core的日誌中看到生成了以下SQL語句:spa

=============================== EF Core log started ===============================
Executed DbCommand (122ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [u].[ID], [u].[CompanyCode], [u].[CreateTime], [u].[DataStatus], [u].[FirstName], [u].[LastName], [u].[MailAddress], [u].[MiddleName], [u].[Password], [u].[UserCode], [u].[Username]
FROM [MD].[User] AS [u]
WHERE [u].[UserCode] LIKE N'%ADMIN%'
=============================== EF Core log finished ===============================

由於EF.Functions.Like方法是EF Core定義的系統函數,因此咱們看到EF Core能夠將該C#方法轉換爲SQL查詢中的LIKE語句做爲查詢的WHERE條件。日誌

 

若是如今咱們將EF.Functions.Like的調用放到咱們自定義的一個C#方法UserCodeLike中去,而後在Expression<Func<User, bool>> userExperssion右邊的lambda表達式中調用自定義方法UserCodeLike,代碼以下所示:code

using EFLambdaExpression.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace EFLambdaExpression
{
    class Program
    {
        static bool UserCodeLike(User user, string pattern)
        {
            return EF.Functions.Like(user.UserCode, pattern);
        }

        static void Main(string[] args)
        {
            using (FinanceDigitalToolContext dbContext = new FinanceDigitalToolContext())
            {
                Expression<Func<User, bool>> userExperssion = u => UserCodeLike(u, "%ADMIN%");

                var users = dbContext.User.Where(userExperssion).ToList();
            }

            Console.WriteLine("Press key to quit....");

            Console.ReadLine();
        }
    }
}

能夠從EF Core的日誌中看到生成了以下SQL語句:blog

=============================== EF Core log started ===============================
Executed DbCommand (124ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [u].[ID], [u].[CompanyCode], [u].[CreateTime], [u].[DataStatus], [u].[FirstName], [u].[LastName], [u].[MailAddress], [u].[MiddleName], [u].[Password], [u].[UserCode], [u].[Username]
FROM [MD].[User] AS [u]
=============================== EF Core log finished ===============================

能夠看到,雖然最後查出來的結果是同樣的,可是此次EF Core對User表作了全表查詢,在SQL的查詢語句中沒有生成任何WHERE條件,說明EF Core不認識咱們定義的UserCodeLike方法,不知道怎麼將UserCodeLike方法轉換爲對應的SQL語句,因此乾脆就作了全表查詢,將User表的數據從數據庫全查出來後,再調用咱們的UserCodeLike方法來過濾數據,若是User表的數據量很是大,這樣效率其實會很是低。全部不建議在EF Core的lambda表達式中使用自定義函數。string

相關文章
相關標籤/搜索