1、緣由
快下班的時候,一同事說在寫linq查詢語句時where條件中寫兩時間相減大於某具體天數報錯;后來仔細一問,經抽象簡化,可以總結為下面的公式:
a、當前時間 減去 某表時間字段 大於 某具體天數 ;簡化后:常量-變量>常量 ;
b、數據庫表某時間字段1 減去 數據庫某時間字段2 大於 某具體天數 ;簡化后:變量-變量>常量 ;
對於上述情況,linq是完全支持a的。那么對於b,則需要繞個圈子,要么將數據加載到內存,然后在內存中計算;要么通過其他方式,比喻在linq語句中直接調用C#的內置函數,這里我們選擇內置函數方式處理。
2、進坑
a、首先想到的是AddDays方法,直接報錯“LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression”,很明顯說不能識別AddDays方法;
b、然后谷歌搜索,說需要用到DbFunctions的擴展函數 AddDays,然后開干修改代碼,竟然又報錯“找不到數據庫函數AddDays”;懵逼了,繼續查資料,然來ef中這個DbFunctions支持sqlserver數據庫;到這里就很明顯了,需要在mysql數據庫中新建函數AddDays;
3、曙光
a、在對應的數據庫中新建函數,命名為:AddDays
1 DELIMITER $$ 2 3 USE `dev`$$ 4 5 DROP FUNCTION IF EXISTS `AddDays`$$ 6 7 CREATE DEFINER=`dev_user`@`%` FUNCTION `AddDays`(a DATETIME,b INT) RETURNS DATETIME 8 BEGIN 9 RETURN DATE_ADD(a, INTERVAL b DAY); 10 END$$ 11 12 DELIMITER ;
按照程序里面的邏輯,這里使用了mysql的內置函數DATE_ADD。
小插曲:剛開始新建函數時老是不成功,后來搜索mysql創建函數,才發現,mysql數據的配置里面有是否允許新建函數的開關,如是用腳本打開開關,再執行上面的函數腳本,就ok了。
b、修改代碼
1 using (var dbContext1 = new MySqlDbContext1("name = MySqlConnectionString_Dev")) 2 { 3 var timeQuery = new MySqlDbProvider<TimeTestEntity>(dbContext1).GetQueryable(); 4 5 var result2 = timeQuery.FirstOrDefault(w => w.Time2 > DbFunctions.AddDays(w.Time1,2)); 6 7 }
c、查看翻譯出來的sql語句如下
1 SELECT 2 `Extent1`.`Id`, 3 `Extent1`.`Name`, 4 `Extent1`.`Time1`, 5 `Extent1`.`Time2` 6 FROM `timetest` AS `Extent1` 7 WHERE (`Extent1`.`Time2`) > (AddDays(`Extent1`.`Time1`, 2))
4、心情舒暢,又搞定了一個問題。