Обновленный ответ:
Если вы перешли по ссылке, которую я дал вам в начале моего ответа, эта недостающая функция тем временем получила 75 голосов и теперь (наконец-то!) реализована Microsoft в EF 6.1 . Всем, кто участвовал: Спасибо за голосование! Ваш голос был услышан.
Например:
var query = from e in context.Employees where e.EmployeeID.ToString() == "1" select e;
теперь будет переведено на:
DECLARE @p0 NVarChar(1000) = '1'
SELECT [t0].[EmployeeID], [t0].[LastName], [t0].[FirstName], [t0].[Title],
[t0].[TitleOfCourtesy], [t0].[BirthDate], [t0].[HireDate], [t0].[Address],[t0].[City],
[t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[HomePhone], [t0].[Extension],
[t0].[Photo], [t0].[Notes], [t0].[ReportsTo], [t0].[PhotoPath]
FROM [Employees] AS [t0]
WHERE (CONVERT(NVarChar,[t0].[EmployeeID])) = @p0
т.е. e.EmployeeID.ToString()
переводится как (CONVERT(NVarChar,[t0].[EmployeeID]))
.
Оригинальный ответ:
Мне не имеет смысла, почему Linq2EF не переводит .ToString()
в правильный оператор SQL, как это делает Linq2SQL, только команда разработчиков Microsoft знает причину, по которой они еще не реализовали это. : - (
Но вы можете повысить приоритет для его реализации, если вы проголосуете за эту функцию , перейдя по этой ссылке.
К счастью, есть также 2 доступных обходных пути , оба из которых я недавно использовал в запросах EF:
I) Что помогло мне обойти это ограничение, так это изменить запрос в список , например:
var customersList = (from c in db.Customers
select c).ToList(); // converts to IEnumerable<T> ...
var customersTest = (from c in customersList
select new {Id=c.ID.ToString()}); // ... which allows to use .ToString()
Оператор .ToList()
преобразуется в IEnumerable<T>
, где доступно .ToString()
. Обратите внимание , что, в зависимости от требований, вы также можете использовать .AsEnumerable()
, что дает преимущество в том, что поддерживается отложенное выполнение, что лучше, если у вас есть несколько запросов linq, зависящих друг от друга, или если вы используя различные значения параметров (большое спасибо Divega за эту подсказку!).
После этого вы можете использовать этот запрос по своему желанию, например ::
var customersTest2 = from c in customersTest
select new
{
Id = c.Id,
Addresses = from a in db.Addresses where c.Id == a.ReferenzId select a
};
Конечно, если вам нужно, вы можете добавить дополнительные свойства к объектам customersTest
по мере необходимости. Вы также можете оптимизировать запрос выше, я использовал только 3 шага для удобства чтения этого примера.
II) Для простых преобразований, и если вам необходимо повторно использовать сгенерированный запрос в дальнейших подзапросах (и он должен остаться IQueryable
), используйте SqlFunctions
из System.Data.Objects.SqlClient
, они будут правильно переведены в запросы SQL.
Пример 1 : преобразование даты (необходимо использовать даты, как показано ниже)
var customersTest = from c in db.Customers
select new {
strDate=SqlFunctions.DateName("dd", c.EndDate)
+"."+SqlFunctions.DateName("mm", c.EndDate)
+"."+SqlFunctions.DateName("yyyy", c.EndDate)
}
Пример 2 : преобразование чисел в строку
var customersTest = from c in db.Customers
select new {
strID=SqlFunctions.StringConvert((double)c.ID)
}
Это должно помочь вам в большинстве ситуаций, когда требуется преобразование в строки.