I've run into a similar problem, where I needed to have a IN in my select query, and the number of elements varied at run time.
I use a parameterized query in the form of a stored procedure and pass in a delimited string containing the list of things I'm looking for. The escaping is automatically handled by the system, no need to take extraordinary steps. Better not make it delimited by characters that will be found in the text you're searching (like commas). a vertical bar ("|") would probably work best in many cases.
By the way, make sure the CRLFs in your table are CHAR(13)+CHAR(10) because the opposite way around isn't \r\n and you wouldn't find it if Environment.NewLine was part of your search.
Here's a stored procedure using a quick and dirty parse resolving to a table that I have used:
CREATE PROCEDURE FindBooks
(
@list varchar(500)
)
AS
CREATE TABLE #parse_table (item varchar(500))
DECLARE @temp VARCHAR(500)
DECLARE @result VARCHAR(500)
DECLARE @str VARCHAR(500)
DECLARE @pos SMALLINT
SET @temp = RTRIM(LTRIM(@list))
SET @pos = 1
WHILE @pos > 0
BEGIN
SET @pos = CHARINDEX('|',@temp)
IF @pos > 0
BEGIN
SET @result = SUBSTRING(@temp,1,@pos - 1)
SET @temp = RTRIM(LTRIM(SUBSTRING(@temp,@pos+1,LEN(@temp) - @pos)))
INSERT INTO #parse_table
SELECT @result
END
ELSE
INSERT INTO #parse_table
SELECT @temp
END
SELECT * FROM Books WHERE Title in (select * from #parse_table)
Simply create your list of book titles as a simple string (containing whatever embedded apostrophes, CRLFs, and so on) and use a parameterized query. Of course, your stored proc can contain other things besides the delimited list.