@MIsternik

Entity Framework связь элементов одной таблицы, чяднт?

Есть некоторая таблица:
[Table("tags")]
    public class Tag
    {
        [ScaffoldColumn(true)]
        [StringLength(60)]
        [Column("id")]
        public string Id { get; set; }

        /* другие поля */

        public virtual ICollection<Tag> ParentTags { get; set; }
        public virtual ICollection<Tag> ChildTags { get; set; }
    }


Нужно связать одни элементы с другими как многие ко многим. Для этого есть таблица tags_relations:
parent_tag_id character varying(60) NOT NULL,
child_tag_id character varying(60) NOT NULL,


и описание связи:
modelBuilder.Entity<Tag>()
                .HasMany<Tag>(a => a.ParentTags)
                .WithMany(a => a.ChildTags)
                .Map(tt =>
                {
                    tt.MapLeftKey("parent_tag_id");
                    tt.MapRightKey("child_tag_id");
                    tt.ToTable("tags_relations");
                });


При сохранении в методе контроллера исключений нет, все ок:
public ActionResult Edit([Bind(Include ="Id,Title,Visible,Description")] Tag tag,string[] ParentTags)
        {
            if (ModelState.IsValid)
            {
                var parentTags = db.Tags.Where(a => ParentTags.Contains(a.Id)).ToList<Tag>();
                tag.ParentTags = parentTags;
                db.Entry(tag).State = EntityState.Modified;
                
                db.SaveChanges();
            }
            var tags = db.Tags.Where(a => a.Visible == false).Select(c => new {
                Id = c.Id,
                Title = c.Title
            }).ToList();
            ViewBag.Tags = new MultiSelectList(tags, "Id", "Title");

            return View(tag);
        }


Но записей в таблице tags_relations не появляется.

Что я делаю не так ?)

Еще вопрос, как можно отследить сгенерированный EF запрос?
  • Вопрос задан
  • 599 просмотров
Решения вопроса 1
@MIsternik Автор вопроса
Внимание ответ! =)
Локализовать причину помогло логирование запросов к базе.
Так как я использую NLog, то это делается так:
// Добавляем объект логгера в контроллер
private static Logger logger = LogManager.GetCurrentClassLogger();

// в самом методе, чтобы отслеживать запросы из него, добавляем:
db.Database.Log = (a) => logger.Info(a);

Всё, запросы пишутся в файл описанный в настройках NLog

Основная проблема решилась изменением кода контроллера с
if (ModelState.IsValid)
{
    var parentTags = db.Tags.Where(a => ParentTags.Contains(a.Id)).ToList<Tag>();
    tag.ParentTags = parentTags;
    db.Entry(tag).State = EntityState.Modified;
                
    db.SaveChanges();
}


на
if (ModelState.IsValid)
{
    var parentTags = db.Tags.Where(a => ParentTags.Contains(a.Id)).ToList<Tag>();
                
    db.Entry(tag).State = EntityState.Modified;
    // перенесли добавление под предыдущую строку и добавляем так, а не приравниванием.
    parentTags.ForEach(a => tag.ParentTags.Add(a));
    db.SaveChanges();
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@kttotto
пофиг на чем писать
Чтобы увидеть какой запрос формирует Entity, в конфиг, в раздел entity, надо добавить
<
<interceptors>
      <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
        <parameters>
          <parameter value="C:\temp\LogOutput.txt" />
          <parameter value="true" type="System.Boolean" />
        </parameters>
      </interceptor>
    </interceptors>


И как то странно Вы связь устанавливаете. Завязываете таблицу саму на себя? Указывая для таблицы связь, Вы должны указать в какой таблице будет внешний ключ на Вашу сущность. Во общем мапинг в таком виде работать не будет.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы