3

次のIEqualityComparerを使用して、比較する前に会社名から特殊文字を次のように削除しています。

 public class CompanyNameIgnoringSpaces : IEqualityComparer<LeadGridViewModel>
    {
        public bool Equals(LeadGridViewModel x, LeadGridViewModel y)
        {
            var delimiters = new[] {' ', '-', '*', '&', '!'};
            return delimiters.Aggregate(x.CompanyName ?? String.Empty, (c1, c2) => c1.Replace(c2, '\0')) 
                == delimiters.Aggregate(y.CompanyName ?? String.Empty, (c1, c2) => c1.Replace(c2, '\0'));
        }

        public int GetHashCode(LeadGridViewModel obj)
        {
            var delimiters = new[] {' ', '-', '*', '&', '!'};
            return delimiters.Aggregate(obj.CompanyName ?? String.Empty, (c1, c2) => c1.Replace(c2, '\0')).GetHashCode();
        }
    }

クエリを実行するときにこれを呼び出すために、私は以下を使用します:

var results = result
                  .GroupBy(c => c, new CompanyNameIgnoringSpaces())
                  .Select(g => new LeadGridViewModel
                  {
                      LeadId = g.First().LeadId,
                      Qty = g.Count(),
                      CompanyName = g.Key.CompanyName,
                  }).OrderByDescending(x => x.Qty).ThenBy(x => x.CompanyName).ToList();

入力文字列(会社名)に一致するすべてのレコードを見つけるために、LINQクエリでこの比較子をどのように使用しますか?

例えば:

 public List<LeadGridViewModel> AllByName(string name, int company)
        {

            var result = (from t1 in db.Leads
                          where
                              t1.Company_ID == company && t1.Company_Name == name...

したがって、t1.Company_Name == nameを使用する代わりに、特殊文字の置換を含めるために、これに等式比較子を使用したいと思います。

4

2 に答える 2

1
  1. linqToDatabase クエリでの IEqualityComparer の使用: プロバイダーが変換できる形式でロジックをカプセル化できない限り、これはローカルで行う必要があります。この問題であなたが取っているルートから、プロバイダーはそれを処理できなかったと思います. したがって、ローカル側で次のことができます。

    1. それをすべて引き出します:

      var results = result.ToArray()
            .GroupBy(c => c, new CompanyNameIgnoringSpaces())
            .Select(g => new LeadGridViewModel
            {
                LeadId = g.First().LeadId,
                Qty = g.Count(),
                CompanyName = g.Key.CompanyName,
            }).OrderByDescending(x => x.Qty).ThenBy(x => x.CompanyName).ToList();
      
    2. 見上げる()

      var results = result
            .ToLookup(c => c, new CompanyNameIgnoringSpaces())
            .Select(g => new LeadGridViewModel
            {
                LeadId = g.First().LeadId,
                Qty = g.Count(),
                CompanyName = g.Key.CompanyName,
            }).OrderByDescending(x => x.Qty).ThenBy(x => x.CompanyName).ToList();
      
    3. 結果をストリーミングする

      var results = result.AsEnumerable()
            .GroupBy(c => c, new CompanyNameIgnoringSpaces())
            .Select(g => new LeadGridViewModel
            {
                LeadId = g.First().LeadId,
                Qty = g.Count(),
                CompanyName = g.Key.CompanyName,
            }).OrderByDescending(x => x.Qty).ThenBy(x => x.CompanyName).ToList();
      

    注: SQL のほとんどのバリアントには置換機能があるため、置換を式にハードコーディングして、サーバー側でこれを行うことができます。再利用可能にしたい場合は、次のようなものが必要です。

    private static Expression<Func<LeadGridViewModel,String>> leadGridTransform = 
        (lead) => lead.CompanyName == null ? "", lead.CompanyName.Replace(' ','\0').Replace.... ;
    

    クエリ可能な式で使用できるもの:

    var results = result.GroupBy(leadGridTransform)....
    

    ここでは、コストのかかるサーバー側の合体操作を避けるため、三項演算子が使用されました。

  2. 特定の文字列のすべてのレコードを検索: ここでは、比較を逆にして、指定された文字列と同等のすべての文字列を検索し、それらに含まれる会社名をクエリします。したがって、db.Leads が LeadGridViewModel のテーブルであると仮定すると、比較子を使用できます。

    1. 暗黙の反転:

      public List<LeadGridViewModel> AllByName(string name, int company)
      {
          var comparer = new CompanyNameIgnoringSpaces();
          var group = db.Leads.Select(lead => new LeadGridViewModel
                                      { CompanyName = lead.CompanyName })
                              .AsEnumerable()
                              .Where(lead => comparer.Equals(name, lead.CompanyName)
                              .ToArray();
      
          var result = db.Leads.Where(lead => lead.Company_ID == company)
                               .Where(lead => group.Contains(lead.CompanyName))...
      
    2. 明示的な反転:

      private var delimiters = new[] {' ', '-', '*', '&', '!'};
      public List<LeadGridViewModel> AllByName(string name, int company)
      {
          var atomicName = name.Trim().Split(delimiters);
          IEnumerable<String> permutations = atomicName.Aggregate(
                    new String[] {""}, 
                    (accumulate,atom) => atom == "" ? accumulate.Join(
                           delimiters,str => true,chr => true,(str,chr) => str + atom + chr.ToString()) : accumelate)
                   .ToArray();
      
          var result = db.Leads.Where(lead => lead.Company_ID == company)
                               .Where(lead => permutations.Contains(lead.CompanyName))...
      

注: 比較の反転については、これらの方法の両方に独自の制限があります。最初の実装では、データベースが大きくなるほど、利用可能なグループ化の構築が遅くなります。2 番目の実装では、名前の区切り文字が多いほど、順列の構築にかかる時間が長くなります (指数関数的に)。置換をハードコーディングする場合、これはサーバー側で実行できるため、これらの制限を回避できます。

于 2012-11-05T18:28:36.480 に答える
1

できません。の呼び出しに使用されるコード (および内部で使用されるコードでさえも) は、IEqualityComparisonSQL クエリに変換できIEqualityComparisonませんExpression

于 2012-11-05T14:09:35.870 に答える