【问题标题】:Linq search database considering duplicates考虑重复的Linq搜索数据库
【发布时间】:2018-11-19 12:59:08
【问题描述】:

我遇到了通过重复列表值搜索数据库的问题。

首先我按给定的字符串搜索所有出现的地方。

var parentIdList =  await _context.ECATEGORIES
            .Where(a => a.NAME.ToLower().Contains(partOfName.ToLower()))
            .ToListAsync(ct);

然后

当给定的 parentIdList 的 PARENTID 等于数据库 ID 时,我检索所有名称

 var mainName = await _context.ECATEGORIES
                .Where(a=> parentIdList.Any(p=>p.PARENTID==a.ID) )
                .Select(s => s.NAME)
                .ToListAsync(ct);

我的问题是,有时属性 PARENTID 是重复的。

例如 PARENTID = {1,1,2,2,4,5,6}

那么结果就是 mainName = {"a","b","c","d","e"}

但我想要 mainName = {"a","a","b","b","c","d","e"}

【问题讨论】:

  • 您要对 ParentId 进行重复数据删除吗?我不明白你的思路,重复的 id 似乎从来都不是一个好主意。
  • 这不是我的数据库,但同事和 ParentId 可以故意复制。
  • 所以你故意想要重复的 id 作为结果,是吗?
  • 我的数据库有唯一的 PK ID,以及引用 PK ID 的 parentid。 ParentId 可以重复并且为空。不要问我为什么会这样,因为这不是我的问题。

标签: database linq any


【解决方案1】:

所以你有一个Categories 的序列,其中每个Category 都有一个Id、一个ParentId 和一个Name。你还有一个字符串partOfName

您想要Categories 中的Names。全部Categories?不,只有那些 Categories 的父级名称看起来像 partOfName看起来像 是通过在您的代码中使用函数 contains 来表示的)

我不确定你是否使用实体框架。您对_context 的使用似乎暗示了这一点。在这种情况下,使用虚拟父属性会更容易。稍后见。

如果您不使用实体框架,我建议您在一次查询中获取数据:将元素与其父元素连接,并仅保留父元素满足您的contains 谓词的连接结果:

string lowerCasePartOfName = partOfName.ToLower(); // for efficiency: do this only once
IQueryable<Category> categories = myDbContext.Categories;
IQueryable<Category> validParents = myDbContext.Categories
   .Where(category => category.Name.ToLower().Contains(lowerCasePartOfName))

现在使用 Category.ParentId = Parent.Id 上的 validParentIds 加入每个类别

var query = Categories.Join(validParents, // join categories with validParents
    category => category.ParentId,         // from each category take the ParentId
    parent => parent.Id,                   // from each valid parent take the Id
    (category, parent) => new              // when they match make one new object
    {
        CategoryName = category.Name,
    });

注意,直到现在查询已经完成,它还没有被执行。如果您愿意,可以将它们连接成一个大的 LINQ 查询。我不确定这是否会大大提高性能;但是,它会降低可读性。

var result = query.ToListAsync();

实体框架解决方案

如果你使用实体框架,你的 Category 类应该是这样的:

class Category
{
     public int Id {get; set;}
     public string Name {get; set;}

     // every Category has zero or one Parent category:
     public int? ParentId {get; set;}
     public Category Parent {get; set;}

     // every Category has zero or more Children, each of them has this Category as Parent
     public virtual ICollection<Category> Children {get; set;}
}

你的查询会简单得多:

给我所有父类名称看起来像 partOfName 的类别的名称

string lowerCasePartOfName = partOfName.ToLower();
var result = myDbContext.Categories
    // keep only the Categories whose name looks like:
    .Where(category => category.Parent.Name.ToLower().Contains(lowerCasePartOfName))
    .Select(category => category.Name);

【讨论】:

  • 我使用 EF,但为什么你使用 Parent 作为类型而不是类型。 Name 和 ParentId 在同一个表中。
  • 再看一遍:Parent 是属性的标识符。属性类型为Category。在我的实体框架示例中,ParentIdName 也在同一个表中。下次,如果您使用实体框架,请给我们您的类。这有助于我们为您解答
  • 好的,我明白了,但仍然不是这样。你写了“给我所有类别的名称,其父母的名称看起来像 partOfName”。我想要“给我所有看起来像 partOfName 的类别,然后添加到每个找到的关于其父名称的类别信息,或者如果没有父名称,则设置为 null”但是感谢您明天的帖子,我会尝试做得更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多