Вы создаете список тегов:
List<Tag> tags = new List<Tag>();
Затем для каждой книги вы устанавливаете свойство Tags
для этого списка.
book.Tags = tags;
Books.Add(book);
Это важно, потому что это означает, что независимо от того, сколько у вас книг, существует только один список тегов.Свойство Tags
каждой книги относится к одному и тому же списку тегов.Все они делятся им.
Это означает, что во втором запросе, когда вы добавляете теги в этот список:
tags.Add(tag);
... вы добавляете этот тег в каждую книгу,В результате у каждой книги будут одинаковые теги, потому что есть только один список.
Что вам, вероятно, нужно, - это просто добавить теги к книгам, с которыми они идут.Чтобы сделать это, вместо создания одного списка тегов, сделайте следующее:
book = new Book()
{
IdBook = idBook,
Title = title,
Tags = new List<Tag>()
};
Теперь у каждой книги будет свой список тегов.Вы можете добавить теги в одну книгу, не добавляя их во все книги.
Вы можете удалить переменные tags
и IdBooks
.Вам не нужно создавать список идентификаторов книг, потому что вы уже создали список книг, и у каждой книги уже есть идентификатор.
Таким образом, вы можете заменить вторую часть метода следующим:
foreach (var book in Books) // loop through the books, not the IDs
{
SqlCommand tagCommand = new SqlCommand();
tagCommand.Connection = con.con;
// in your query, get the ID from the book
tagCommand.CommandText = "SELECT t.IdTag,t.Name FROM tblTag t LEFT OUTER JOIN tblBookTag bt ON bt.idTag = t.idTag WHERE bt.idBook = @ID";
tagCommand.Parameters.AddWithValue("@ID", book.IdBook);
SqlDataReader tagReader = tagCommand.ExecuteReader();
if (tagReader.HasRows)
{
while (tagReader.Read())
{
Tag tag = new Tag();
var idTag = Convert.ToInt32(tagReader["IdTag"]);
var name = tagReader["Name"].ToString();
tag.IdTag = idTag;
tag.Name = name;
// Add the tag to the collection of tags for just that one book.
book.Tags.Add(tag);
}
tagReader.Close();
}
}
Чтобы упростить отладку, я бы также подумал о том, чтобы поместить часть, которая получает теги, в отдельную функцию, например:
List<Tag> GetTags(int bookId)
и переместить кодкоторый ищет теги для каждой книги там.Таким образом, ваша основная функция будет выглядеть следующим образом:
foreach(var book in Books)
{
book.Tags = GetTags(book.IdBook);
}
Это похоже на перемещение кода, но это приведет к меньшим функциям, которые легче читать.Когда вы перемещаете код, вы можете понять, что используете какую-то переменную, которую, как вы думали, вы не использовали, и это поможет вам уловить проблему.
Таким образом, если часть, которая доставляет вам неприятности, этофункция, которая получает теги для книги, теперь вы можете проверить ее отдельно, вызвав ее с одним идентификатором книги и посмотрев, что вы получите обратно.Если вы получили неправильный результат, вы можете отладить метод, используя только один идентификатор книги.
Отладка становится проще, когда мы можем работать с небольшими фрагментами кода.Если мы знаем, что одна часть работает, мы можем перестать смотреть на нее или запускать ее снова и просто посмотреть на часть, которая не работает.
Обновление 2 (извините, это прошло далекоТочка, где это полезно для всех, кто читает это, но теперь нет пути назад.)
Измените это:
foreach (var bk in Books)
{
book.Tags = GetTagsThatMatch(bk.IdBook);
}
на это:
foreach (var bk in Books)
{
bk.Tags = GetTagsThatMatch(bk.IdBook);
}
Если вы добавите теги в book
, то добавите их в последнюю созданную книгу, а не в текущую книгу в цикле foreach
.
Чтобы избежать этой путаницы.удалите эту строку:
Book book = new Book();
и объявите переменную в том месте, где вы ее используете:
Book book = new Book()
{
IdBook = idBook,
Title = title,
Tags = new List<Tag>()
};
Объявляя переменную внутри области действия этого цикла, становится невозможным случайноиспользуйте это вне этой области.Полезно хранить переменные в наименьшей возможной области видимости.