При подготовке моделей для MS SQL Compact Edition зачем использовать собственные ссылки и ключи идентификаторов одновременно для связывания объектов / сущностей?

#c# #sql #asp.net-mvc #associations

#c# #sql #asp.net-mvc #ассоциации

Вопрос:

В процессе обучения ASP.NET , я следую этому руководству для ASP.NET MVC4: http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-4

Автор готовит классы для создания базы данных и размещения ее экземпляров в этой базе данных. Он определяет, например, класс Album:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcMusicStore.Models {
    public class Album {
        public int AlbumId { get; set; }
        public int GenreId { get; set; }
        public int ArtistId { get; set; }
        public string Title { get; set; }
        public decimal Price { get; set; }
        public string AlbumArtUrl { get; set; }
        public Genre Genre { get; set; }
        public Artist Artist { get; set; }  
    }
}
  

Почему мы должны хранить избыточную информацию об ассоциациях с другими объектами?Мы получили: GenreId и собственную ссылку Genre . В чем смысл этого? Насколько я знаю, база данных отношений содержит идентификаторы, а не ссылки. Поэтому мы должны сохранять только идентификаторы.

Ответ №1:

Назначение свойства reference — разрешить Entity Framework загружать связанные данные для этой ссылки, явно или неявно (отложенная загрузка). С помощью свойства reference вы можете:

 album.Genre.Name;
  

Чтобы получить название жанра (при условии, что у него есть свойство called Name ). Однако без ссылки вам пришлось бы сделать что-то вроде:

 var genre = context.Genres.Find(album.GenreId);
genre.Name;
  

Однако реальная сила заключается в возможности комбинировать запросы. Если вы используете ссылочные свойства и извлекаете свой альбом, например:

 context.Albums.Include("Genre").Find(albumId);
  

Затем, когда вы обращаетесь к свойству like album.Genre.Name , дальнейшие запросы не выдаются. Entity Framework выполнила объединение за кулисами и загрузила все данные сразу. В то время как без свойства reference вам пришлось бы выполнить два запроса, чтобы добраться сюда. Это еще более эффективно, если учитывать уровни ссылочных свойств. Предположим, например, что ваш Artist объект также имеет свойство ссылки на вызываемый класс Tour , и, допустим, у каждого Tour есть свойство навигации по коллекции Show , которое будет отдельным шоу в этом туре. Затем вы могли бы сделать:

 context.Albums.Include("Artist.Tours.Shows").Find(albumId);
  

И одновременно запрашивать не только альбом и исполнителя, но и все туры, которые есть у этих артистов, и все шоу в каждом из этих туров. Конечно, это большой запрос, но это один запрос — это важная часть. Без этих ссылочных свойств вам пришлось бы делать что-то вроде:

 var album = context.Albums.Find(albumId); // 1 query
var artist = context.Artists.Find(album.ArtistId); // 1 query
var tours = context.Tours.Where(m => m.ArtistId == artist.Id); // 1  query
foreach (var tour in tours)
{
    var shows = context.Shows.Where(m => m.TourId == tour.Id); // N queries
    foreach (var show in shows)
    {
        // do something with show
    }
}
  

Сейчас вы выдаете тонну запросов, чтобы получить нужные вам данные, тогда как вы могли бы просто использовать один со ссылочными свойствами.