选择模型属性在键值对列表中包含all的位置

时间:2012-01-20 21:34:34

标签: c# linq nhibernate linq-to-nhibernate

我有以下课程

public class Account
{
    IEnumerable<AccountData> Data { get; set; }
}

其中AccountData为

public class AccountData
{
    public virtual long Id { get; set; }
    public virtual AccountTag AccountTag { get; set; }
    public virtual string Value { get; set; }
}

和帐户标记

的位置
public class AccountTag
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }
}

我想返回数据字段位于键值对列表中的所有帐户。 long是AccountTag.Id,AccountData.Value包含字符串

这是我到目前为止所做的,但这是在Web服务器上执行的,可能会有数千个帐户返回,所以我正在寻找一个linq到sql版本。

public IEnumerable<Account> FindByCompanyDataTags(long companyId, IEnumerable<KeyValuePair<long, string>> tags)
{
    var tempAccounts = (from acc in this.Data where acc.Company.Id == companyId orderby acc.Name select acc);
    IList<Account> accounts = new List<Account>();

    foreach (var account in tempAccounts)
    {
       var matches = true;
       foreach (var t in tags)
       {
          if (account.Data.Any(x => x.AccountTag.Id == t.Key && x.Value.Contains(t.Value)))
          {
            continue;
          }

          matches = false;
          break;
        }

        if (matches)
        {
          accounts.Add(account);
        }
      }

      return accounts;
}

如果我使用resharper将其转换为linq表达式,我会得到以下内容

public IEnumerable<Account> FindByCompanyDataTags(long companyId, IEnumerable<KeyValuePair<long, string>> tags)
{
  var tempAccounts = (from acc in this.Data where acc.Company.Id == companyId orderby acc.Name select acc);
  IList<Account> accounts = (from account in tempAccounts let matches = tags.All(t => account.Data.Any(x => x.AccountTag.Id == t.Key && x.Value.Contains(t.Value))) where matches select account).ToList();

  return accounts;
}

但是当我运行这个时,我得到一个不支持异常的方法。

这真让我困惑,有什么建议吗?

1 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为在第一种情况下,您在此处foreach执行期间准备了对db的查询

foreach (var account in tempAccounts)
{....}

你得到Account个对象的集合,并在内存中的客户端使用它们(换句话说,你正在使用Linq对象)

在第二种情况下,您正在尝试执行Linq to Sql查询,但提供程序无法将您的KeyValuePair对象转换为sql查询,因此它会引发异常。

<强>更新

尝试使用IQueryable并构建您的查询,然后应用Where子句:

IQueryable<Account> tempAccountsWithWhere = tempAccounts;
foreach (var tag in tags)
{
    tempAccountsWithWhere = tempAccountsWithWhere.Where(
        a => a.Data.Any(
            ad => ad.AccountTag.Id == tag.Key && ad.Value.Contains(tag.Value)));
}
IList<Account> accounts = tempAccountsWithWhere.ToList();