Мегафункция для тегов

Задача: в базе хранятся теги и теги к контенту (связь тег-контент).
Пользователь вводит свои теги (String[] tagTitles) к контенту.
Среди введенных пользователем тегов могут быть как совсем новые, так и уже существующие в базе.
Новые теги необходимо добавить в таблицу тегов и в таблицу связи тег-контент.
У уже существующих тегов необходимо увеличить поле количества использований на 1.

Структура таблиц

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Table("ContentTag")]
    public class ContentTag
    {
        public int Id { get; set; }
        public int TagId { get; set; }
        public virtual Tag Tag { get; set; }
        public int ContentId { get; set; }
        public int TimesUsed { get; set; }
    }
 
	[Table("Tag")]
    public class Tag
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public int TimesUsed { get; set; }
    }

Функция с багом

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private void AttachTagsToContent(String[] tagTitles, Content content)
        {
            var tags_ = tagTitles.GroupJoin(
                this.dbContext.Tag,
                title => title,
                tag => tag.Title,
                (title, tag) => new { Title = title, Tag = tag.FirstOrDefault(), IsNew = tag.Any() == false });
 
            var newTags = tags_.Where(tag => tag.IsNew).Select(tag => tag.Title);
 
            var tagsAndContentTagsToUpdate = tags_
                .Where(tag => tag.IsNew == false)
                .Select(tag => tag.Tag)
                .Join(
                    this.dbContext.ContentTags,
                    tag => tag.Id,
                    contentTag => contentTag.Tag.Id,
                    (tag, contentTag) => new { Tag = tag, ContentTag = contentTag });
 
            foreach (var title in newTags)
            {
                var tag = new Tag() { Title = title };
                var contentTag = new ContentTag() { ContentId = content.Id, Tag = tag };
                this.dbContext.ContentTags.Add(contentTag);
            }
 
            foreach (var tagAndContentTag in tagsAndContentTagsToUpdate)
            {
                tagAndContentTag.Tag.TimesUsed++;
                tagAndContentTag.ContentTag.TimesUsed++;
            }
 
            this.dbContext.SaveChanges();
        }

В чем собственно баг.

Теги и теги к контенту.

Варианты:

Тега нет ни в тегах, ни в контенте — тег добавляется в теги и в контент
Тег есть в тегах, но нет в контенте — тег плюсуется в тегах и добавляется в контент
Тег есть и в тегах и в контенте — тег плюсуется в тегах и в контенте
Тега нет в тегах, но есть в контенте — это ошибка, такого не должно быть

Пусто везде.

750: «мухи», «собаки», «медведи», «старый тег»
Добавились в две таблицы

610: «мухи», «собаки», «медведи», «старый тег»
Увеличились в тегах, увеличились в контенте у 750й

610: «кошки», «мышки», «носороги», «новый тег»
Добавились в обе таблицы

610: «мухи», «собаки», «медведи»
Увеличились в тегах, увеличились у 750й

610: «кошки», «мышки», «носороги»
Увеличиличь в тегах, увеличились у 610й

609: «кошки», «мышки», «носороги», «пулемет»
кмн увеличились, п добавился
кмн увеличиличь у 610й, п добавился к 609й

833: «кошки», «собаки», «огурец»
в тегах добавилось-увеличилось как надо,
в тег-контенте собаки увеличились у 750, кошки — у 610, к 833 добавился только огурец

почему-то если тег есть в таблице тегов и у какого-то контента, то если мы пытаемся добавить этот тег к другому контенту, то он увеличивается у первого

Измененный вариант с исправленным багом

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
private void AttachTagsToContent(String[] tagTitles, Content content)
        {
            var tags_ = tagTitles.GroupJoin(
                this.dbContext.Tag,
                title => title,
                tag => tag.Title,
                (title, tag) => new { Title = title, Tag = tag.FirstOrDefault(), IsNew = tag.Any() == false });
 
            var newTags = tags_.Where(tag => tag.IsNew).Select(tag => tag.Title);
 
            var tagsAndContentTagsToUpdate = tags_
                .Where(tag => tag.IsNew == false)
                .Select(tag => tag.Tag)
                .GroupJoin(
                    this.dbContext.ContentTags,
                    tag => tag.Id,
                    contentTag => contentTag.Tag.Id,
                    (tag, contentTag) => new { Tag = tag, ContentTag = contentTag.SingleOrDefault(ct => ct.ContentId == content.Id) });
 
            foreach (var title in newTags)
            {
                var tag = new Tag() { Title = title };
                var contentTag = new ContentTag() { ContentId = content.Id, Tag = tag };
                this.dbContext.ContentTags.Add(contentTag);
            }
 
            foreach (var tagAndContentTag in tagsAndContentTagsToUpdate)
            {
                tagAndContentTag.Tag.TimesUsed++;
 
                if (tagAndContentTag.ContentTag == null)
                {
                    var contentTag = new ContentTag()
                    {
                        ContentId = content.Id,
                        Tag = tagAndContentTag.Tag
                    };
 
                    this.dbContext.ContentTags.Add(contentTag);
                }
                else
                {
                    tagAndContentTag.ContentTag.TimesUsed++;
                }
            }
 
            this.dbContext.SaveChanges();
        }

Оставить комментарий


Примечание - Вы можете использовать эти HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>