It seems to me like you're putting the cart a bit before the horse, especially since you have a partial implementation alreadyyou have a partial implementation already. Take a step back and ask yourself what "all" means and what purpose it serves.
In this case it means "without conditions or filters", and the purpose is to provide a way for the user to tell the system "I don't care what the tags are". Its meaning becomes relevant at the point where you examine the actual value of the tags, which doesn't happen until you get to the DB query. Before that, the value of the tag doesn't matter. You can just pass it through your business objects as normal.
all documents from tag X that were published on website tagged Y
I'd write such a query like this (pseudo-SQL, proper syntax, e.g. ON, omitted for brevity):
FROM documents
INNER JOIN tags
INNER JOIN publishedOn
INNER JOIN websites
WHERE tag = X AND website = Y
If X is "all", then I'd do it like this:
FROM documents
INNER JOIN publishedOn
INNER JOIN websites
WHERE website = Y
Tags are not queried because they aren't relevant. The user selected "all" which means "I don't care what tag the document has". Here, you make a decision at the data access layer and choose the second query if you see that. If you'd rather keep your DAL simpler and make the decision within the SQL query itself, that's easy to do:
FROM documents
INNER JOIN tags
INNER JOIN publishedOn
INNER JOIN websites
WHERE (X = all OR tag = X) AND website = Y
If you use a query like this, you might run into the "magic number" problem, meaning "what value do I compare X against to see if it means all?" A common pitfall is using a hardcoded literal for comparison. For example, @tagID = -1
. This is bad. What you've described doing - adding "all" as a "virtual tag" - is a way to prevent this problem, but it's far complicated than is necessary.
Again, ask yourself what the meaning of "all" represents in relation to your tags. It's "I don't care" or, more precisely, "unspecified". There's a value for that already: null. If the user picks "all", then set the tag filter property on your BO to null. When it's time to inspect the filter, if it's null, don't filter. The choice between performing the inspection in the DAL or DB is a question of where you want to put the little bit of extra complexity (which implies a minor maintenance increase and a performance hit which ought to be negligible).
Bottom line: don't treat "all" as a tag because it isn't one. Trying to crowbar it in will make things difficult and confusing for whoever maintains the code in the future.