2

我正在尝试使用 LINQ for Entities(EF4 代码优先)选择一些记录。

我有一个名为 Monitoring 的表,其中包含一个名为 AnimalType 的字段,其值如下

  • “狮子,老虎,山羊”
  • 《蛇、狮、马》
  • “响尾蛇”
  • 《山狮》

我想在字符串数组 (animalValues) 中传递一些值,并从 Monitorings 表返回其中字段 AnimalType 中的一个或多个值与 animalValues 中的一个或多个值匹配的行。以下代码几乎可以按我的意愿工作,但我发现我采用的方法存在一个重大缺陷。

public IQueryable<Monitoring> GetMonitoringList(string[] animalValues)
    {
        var result = from m in db.Monitorings
                     where animalValues.Any(c => m.AnimalType.Contains(c))
                     select m;
        return result;
    }

为了解释这个问题,如果我传入 animalValues = { "Lion", "Tiger" } 我发现选择了三行,因为第 4 条记录“Mountain Lion”包含它认为的“Lion”这个词匹配。

这不是我想要发生的。我需要“Lion”来匹配“Lion”而不是“Mountain Lion”。

另一个例子是,如果我传入“Snake”,我会得到包含“Rattlesnake”的行。我希望有人有更好的 LINQ 代码,它允许匹配精确的逗号分隔值,而不仅仅是匹配“响尾蛇”的“蛇”中的一部分。

4

2 回答 2

4

这是一种可以完成工作的hack:

public IQueryable<Monitoring> GetMonitoringList(string[] animalValues)
{
    var values = animalValues.Select(x => "," + x + ",");
    var result = from m in db.Monitorings
                 where values.Any(c => ("," + m.AnimalType + ",").Contains(c))
                 select m;
    return result;
}

这样,您将拥有

  • “,狮子,老虎,山羊,”
  • “,蛇,狮子,马,”
  • “,响尾蛇,”
  • “,山狮,”

并检查“,Lion”和“Mountain Lion”是否匹配。

很脏,我知道。

于 2012-07-03T14:32:35.703 回答
2

因为您的字段中的数据是用逗号分隔的,所以您确实需要单独分解这些条目。由于 SQL 并不真正支持拆分字符串的方法,因此我想出的选项是执行两个查询。

第一个查询使用您开始使用的代码,至少可以让您大致了解并最大限度地减少您要检索的数据量。它将其转换为 aList<>以实际执行查询并将结果带入内存,这将允许访问更多扩展方法,例如Split().

第二个查询使用内存中的数据子集并将其与您的数据库表连接,然后提取完全匹配:

public IQueryable<Monitoring> GetMonitoringList(string[] animalValues)
{
    // execute a query that is greedy in its matches, but at least
    // it's still only a subset of data. The ToList()
    // brings the data into memory, so to speak
    var subsetData = (from m in db.Monitorings
             where animalValues.Any(c => m.AnimalType.Contains(c))
             select m).ToList();

    // given that subset of data in the List<>, join it against the DB again
    // and get the exact matches this time
    var result = from data in subsetData
            join m in db.Monitorings on data.ID equals m.ID
            where data.AnimalType.Split(',').Intersect(animalValues).Any ()
            select m;        

    return result;
}
于 2012-07-03T01:54:56.307 回答