2016-08-09 13 views
0

次のエラーが表示されますが、ステートメントの書き換え方法がわかりません。 アイデアエンティティフレームワーク - 文字列変換エラー

エラー:

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ステートメントに、あなたの表現を翻訳する必要があることを意味します。カスタムConvertメソッドは、データベースサーバー上にも存在するものではなく、C#コードであるため、変換できません。

あなたはすでにアカウントIDを渡しているので、これは一意であると仮定したり、多数のオブジェクトを取得していないことを保証するために一意に近いところまで十分に絞り込んでください。次に、オブジェクトグラフをマテリアライズしてから、C#(linqオブジェクト)にフィルタを適用することができます。これは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

これは、あなたに合った、あなたはReplaceを使用して、あなたのコメントに

@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(char, char)は動作しませんが、Replace(string, string)となります。

0

最初の問題は、変換呼び出しがC#であり、SQLに変換できないことです。すべての関数ができるわけではありませんが、一部の部分文字列はEntity Frameworkにとって「既知」であり、適切なSQLに変換することができます。したがって、EFが認識している文字列関数を使用するように文を書き直すか、論理をデータベースにプッシュする必要があります。

@Imadは、すでにEFに知らあるstring.Replaceを使うことを提案しているが、もちろん、あなたが可能なすべての非数字文字取り除く手助けするつもりはない - あなたが明示的にするためにコーディングしているだけのもの、のように「 - 」を、 'extension'のような他のアルファ文字列は含みません。

これを高速にしたい場合は、「クリーニング済み」の数値を別々のフィールドに保存することをお勧めします。その後、クエリは

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

ええ、それは間違いなくあなたが望むよりも迷惑な努力です。 –