Question

I have the following entities:

[Table("Entities")]
public abstract class Entity { 
 public int EntityID { get; set; } 
 public string Description { get; set; }
 public virtual ICollection<Tag> Tags { get; set; }
}

And the Tag Entity:

public class Tag {
    public int TagID { get; set; }
    public int EntityID { get; set; }
    public string TagValue { get; set; }
}

As the above makes sort of clear Tags are not reused just stored as strings. This has made determining whether Entities share tags slightly more difficult (and slow).

I have a working search to return a list of entities in which the entities contain any of the tags:

List<string> searchTags = new List<String> {"test1", "test2"};
entities = (_entityRepository.Entities
            .Where(o=>o.Tags.Any(f=>searchTags.Contains(f.TagValue)));

Now I also need to return a list of Entities which contain all of the tags in the list. As a non-property variable cannot be passed into a Contains method I cannot just reverse the order of the call with an all, but this is basically what I am trying to achieve:

entities = (_entityRepository.Entities
            .Where(o=>o.Tags.All(f=>f.TagValue.Contains(searchTags)));

I think I have just hit the point where I need to correct the DB schema to re-use Tags which should provide a general performance benefit when filtering my entities on lists of Tags, but I still wanted to ask the following questions:

  1. Am I over complicating this and is there a simple Linq statement which accomplishes this or,
  2. Is this something for which I would should use predicate builder to set my criteria?
Était-ce utile?

La solution

This can be done like this:

var query = _entityRepository.Entities.Select(e => e);
query = searchTags.Aggregate(query, (current, tag) => current.Where(e => e.Tags.Any(t => t.TagValue == tag)));
var result = query.ToList();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top