Отношения Entity Framework многие ко многим не работают

#asp.net #sql #asp.net-mvc #entity-framework #many-to-many

#asp.net #sql #asp.net-mvc #entity-framework #многие ко многим

Вопрос:

У меня проблема с использованием EF 4.1 и отношений «многие ко многим». Я решил использовать подход database first (хотя у меня возникла та же проблема с подходом code first), и я создал модель базы данных:

введите описание изображения здесь

У меня есть отношения «многие ко многим» между таблицами изображений и тегов. В БД она создается как новая таблица с именем «PictureTag» с полями «Picture_Id» и «Tag_Id».

Я добавляю данные в свою базу данных с помощью следующего фрагмента кода:

 if (tags != null)
{
    foreach (HtmlNode tagNode in tags)
    {
        string tagString = tagNode.InnerText.Remove(0, 1);
        Tag tag;
        if (db.Tags.Any(q => q.TagName == tagString))
        {
            tag = db.Tags.Single(q => q.TagName == tagString);
        }
        else
        {
            tag = new Tag { TagName = tagString };
        }
        pic.Tags.Add(tag);
    }
}
List<DbEntityValidationResult> list = db.GetValidationErrors().ToList();
db.Pictures.Add(pic);
db.SaveChanges();
  

Это, конечно, всего лишь часть моего кода. Это часть моей функции поиска. Код работает нормально, не генерирует никаких ошибок и работает в одном контексте БД.

После выполнения этой функции я могу видеть данные в своей БД, все три изображения, теги и объекты в таблице PictureTag.

Тем не менее, когда я пытаюсь поместить в свой просмотр изображения и теги, соответствующие этому изображению, я не вижу никаких тегов. Например, ни к одному из изображений не было прикреплено никаких тегов. Я знаю, что это неправда, потому что я вижу данные в своей БД, поэтому я не знаю, что не так…

На мой взгляд, это код:

 @model IEnumerable<SikSolution.Picture>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
@foreach (var item in Model)
{

    <div>
        <img src="@item.Link" alt="@item.Name" />
        <br />
        <span>
            Tags: @foreach (var tag in item.Tags)
                  {
                      Html.Label(tag.TagName   ", ");
                  }
        </span>
    </div> 
}
  

Я действительно не знаю, что не так… Я был бы признателен за любой совет или указание мне в правильном направлении.

Спасибо!

Ответ №1:

Возможное объяснение заключается в том, что вы не используете отложенную загрузку, а также не загружали свою Picture коллекцию, включая связанные теги (быстрая загрузка). Это должно выглядеть так:

 //...
var pictures = db.Pictures.Include("Tags") // or Include(p => p.Tags) in EF 4.1
    .Where(...)
    .ToList();

return View(pictures);
  

Комментарии:

1. Большое вам спасибо, я понятия не имел, что теперь мне нужно явно сообщить моей коллекции, что я хочу что-то к ней прикрепить. Это новое в EF 4.1?

2. @Tromax: Нет, это не ново. В EF всегда было три способа загрузки свойств навигации: отложенная загрузка, быстрая загрузка и явная загрузка. Это не изменилось с EF 4.1. Вот обзор об этом: blogs.msdn.com/b/adonet/archive/2011/01/31/… Если вы не хотите использовать Include в своих запросах, вы можете использовать отложенную загрузку, тогда загрузка произойдет «автоматически», и ваш исходный код будет работать. Однако отложенная загрузка приводит к многократным обходам в БД.