【问题标题】:Linq not in select on datatableLinq 不在数据表上的选择中
【发布时间】:2010-11-12 23:32:15
【问题描述】:

您好,我有 2 个数据表(bannedlist、countrylist),都包含国家名称列表和 cc 列和国家/地区中的 cods。我正在尝试进行查询,我可以从 countrylist 表中选择不在禁止列表表中的国家,以创建第三个表。

有什么想法吗?

我还没有走得太远。

        var ccList = ds.Tables[2].AsEnumerable(); 
        var bannedCCList = ds.Tables[1].AsEnumerable();
        var query = from r in ccList....

..

尝试后

var bannedCCList = ds.Tables[1].AsEnumerable();
    var query = from r in ccList where !bannedCCList.Any(b => b["cc"] == r["cc"])select r;

我仍然得到相同的国家名单。禁止的还没有被删除。这里有更多细节以便解释更多。不知道我做错了什么

 protected void BindCountryBan(string subd)
{
    DataSet ds = new DataSet();
    ds = new DB().CountryBan_GetSiteSettings();

        BannedCountryListBox.DataSource = ds.Tables[1];
        BannedCountryListBox.DataValueField = "cc";
        BannedCountryListBox.DataTextField = "country";
        BannedCountryListBox.DataBind();

//bind country list
    var ccList = ds.Tables[2].AsEnumerable(); 
    var bannedCCList = ds.Tables[1].AsEnumerable();
    var query = from r in ccList where !bannedCCList.Any(b => b["cc"] == r["cc"])select r;
    //var query = ccList.Except(bannedCCList); 




    //CountryListBox.DataSource = ds.Tables[2];
    DataTable boundTable = query.CopyToDataTable<DataRow>();
    CountryListBox.DataSource = boundTable;
    CountryListBox.DataValueField = "cc";
    CountryListBox.DataTextField = "country";
    CountryListBox.DataBind();
}

【问题讨论】:

  • 在重新思考我的问题后,我已经意识到,而不是玩并试图解决它,而是在我的 sql 查询中添加一个小的 where “选择 * from country_list where cc not in(select cc from country_list_banned_countries where subdomain=@subdomain ) order by country asc" 我可以从服务器端的国家列表中提取被禁止的国家,并毫不费力地绑定。谢谢大家

标签: c# linq datatable


【解决方案1】:

如果你在国家序列上使用它会起作用:

using System.Linq;
...

    var ccList = from c in ds.Tables[2].AsEnumerable()
                 select c.Field<string>("Country"); 
    var bannedCCList = from c in ds.Tables[1].AsEnumerable()
                       select c.Field<string>("Country");
    var exceptBanned = ccList.Except(bannedCCList);

如果您需要未禁止国家/地区的完整行,您可以尝试左外连接:

    var ccList = ds.Tables[2].AsEnumerable();
    var bannedCCList = ds.Tables[1].AsEnumerable();
    var exceptBanned = from c in ccList
                       join b in bannedCCList
                         on c.Field<string>("Country") equals b.Field<string>("Country") into j
                       from x in j.DefaultIfEmpty()
                       where x == null
                       select c;

【讨论】:

  • 谢谢!你的左外连接按我的预期工作,如果你愿意,还有一个问题。请参阅我关于 Meta-Knight 回答的注释。我设法通过将查询结果转换为表来将结果绑定到列表框。有没有更好的绑定方式?
  • 尝试将 ListBox 的 DataTextField 和 DataValueField 值设置为您要绑定的字段的名称。您不需要复制到表中。
  • 请“dahlbyk”我需要 VB.Net 中的第二个代码我在使用“converter.telerik.com”进行转换时遇到了麻烦,谢谢补充
【解决方案2】:

您可以像这样使用 except() LINQ 扩展方法:

var result = full.Except(banned);

但是,这将适用于包含类型的默认比较器。因此,如果您想使用示例中的特定列,您可能需要另一种方法,例如:

from r in ccList
where !bannedCCList.Any(b => b["cc"] == r["cc"])
select r;

使用 except() 意味着两个集合中的引用是相同的,我认为 Tables 不是这种情况,如果我错了,请纠正我。

【讨论】:

  • 赞!我必须将 List 与数据表结合起来,并对您的示例进行了轻微修改,它就像一个魅力。
【解决方案3】:

试试这个:

var query = ccList.Except(bannedCCList);

【讨论】:

  • 你需要:使用 System.Linq;
  • 当我将查询绑定到列表框时,我得到的只是 System.Data.DataRow 看起来我又做错了什么
  • 好的,我已经用 DataTable boundTable = query.CopyToDataTable(); 将它转换为数据表;但我不确定这是最好的方法
  • 虽然这也是一种解决方案,但对于较少的记录来说速度很快,而当列表像 200k 时,这种方法会很慢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-01
  • 1970-01-01
相关资源
最近更新 更多