2016-08-09 2 views
0

Я получаю следующую ошибку, но я не уверен, как переписать мое заявление? Любые идеи?Entity Framework - ошибка преобразования строки

Ошибка:

LINQ to Entities does not recognize the method 'System.String Convert(System.String)' method, and this method cannot be translated into a store expression

Код:

public Client FindClientByMobile(string mobile, string accountId) 
{ 
    Client client = RepositorySet.Include("Account").FirstOrDefault(c => c.AccountId == accountId && !c.IsDeleted 
      && ((Convert(c.TelephoneHome) == mobile) || (Convert(c.TelephoneMobile) == mobile) || (Convert(c.TelephoneWork) == mobile))); 
    return client; 
} 

public static string Convert(string mobile) 
{ 
    var filterNumber = from letter in mobile 
         where char.IsDigit(letter) 
         select letter; 

    StringBuilder number = new StringBuilder(); 
    number.Append(filterNumber.ToArray()); 

    return number.ToString(); 
} 
+2

Ошибка означает, что Linq необходимо преобразовать ваше выражение в оператор Sql. Ваш собственный метод 'Convert' не является переводимым, потому что это код C#, а не тот, который также существует на сервере базы данных. – Igor

+0

Привет, спасибо, но я уже сказал вопрос, я спросил, но я не уверен, как переписать мое заявление? –

+0

номер телефона находится в строке –

ответ

4

Ошибка означает, что Linq нужно перевести выражение в Sql заявление. Ваш пользовательский метод конвертации не может быть переводимым, потому что это код C#, а не тот, который также существует на сервере базы данных.

Поскольку вы уже указываете идентификатор своей учетной записи, я собираюсь предположить, что это либо уникальное ИЛИ фильтрует его достаточно, чтобы он был близок к уникальному, чтобы гарантировать, что вы не получаете большое количество объектов. Затем вы можете материализовать граф объектов и затем фильтровать больше в C# (linq to objects). Это делается с помощью вызова ToList().

public Client FindClientByMobile(string mobile, string accountId) 
{ 
    var clients = RepositorySet.Include("Account").Where(c => c.AccountId == accountId && !c.IsDeleted).ToList(); 
    return clients.FirstOrDefault(client => Convert(client.TelephoneHome) == mobile || Convert(client.TelephoneMobile) == mobile || Convert(client.TelephoneWork) == mobile); 
} 
+0

Это довольно умно. Хорошее место! –

1

ли это вас устраивает, как вы упомянули в своем комментарии

@Imad, what im trying to do is validate, so if the number has been stored in the database as 0331-9000-100, I want to remove all non numeric characters, mobile has already had this applied, so mobile = 033319000100

public Client FindClientByMobile(string mobile, string accountId) 
{ 
    Client client = RepositorySet.Include("Account").FirstOrDefault(c => c.AccountId == accountId && !c.IsDeleted 
      && ((c.TelephoneHome.Replace("-","") == mobile) || (Convert(c.TelephoneMobile) == mobile) || (Convert(c.TelephoneWork) == mobile))); 
    return client; 
} 

с помощью Replace вы можете также заменить другие символы, такие как ( и ) также.

Пункт для запоминания: Replace(char, char) не будет работать, но Replace(string, string) будет.

0

Первая проблема заключается в том, что вызов Convert является C# и не может быть переведен в SQL. Не все функции могут, но некоторые (подстрока, например) являются «известными» для Entity Framework и могут преобразовывать их в appopriate SQL. Таким образом, вам нужно либо переписать инструкцию, чтобы использовать строковые функции, которые EF знает, или иным образом перевести логику в базу данных.

@Imad уже предложил использовать string.Replace, который является известно EF, но, конечно, он не собирается, чтобы помочь вам удалить весь возможный не-цифровой символ - только те, которые вы явно кодирующие, как «-», но не другие альфа-строки, такие как «расширение».

Если вы хотите сделать это быстро, может быть хорошей идеей хранить «очищенные» номера в отдельных полях. Затем запрос становится

Client client = RepositorySet.Include("Account").FirstOrDefault(c => c.AccountId == accountId && !c.IsDeleted 
     && (c.TelephoneHomeClean == mobile) || (c.TelephoneMobileClean == mobile) || (c.TelephoneWorkClean == mobile))); 
return client; 

и у вас есть что-то, что можно сделать намного быстрее и проиндексировано.

+0

хорошая идея в долгосрочной перспективе, поскольку мне нужно будет написать несколько SP для аудита/обновления данных. –

+0

Да, это определенно более раздражающее усилие, чем вы могли бы захотеть. –

Смежные вопросы