Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为MS SQL Compact Edition准备模型时,为什么同时使用本机引用和ID键来关联对象/实体?_C#_Sql_Asp.net Mvc_Associations - Fatal编程技术网

C# 为MS SQL Compact Edition准备模型时,为什么同时使用本机引用和ID键来关联对象/实体?

C# 为MS SQL Compact Edition准备模型时,为什么同时使用本机引用和ID键来关联对象/实体?,c#,sql,asp.net-mvc,associations,C#,Sql,Asp.net Mvc,Associations,在学习ASP.NET的过程中,我将遵循以下有关ASP.NET MVC4的教程: 作者准备创建数据库并将其实例放入该数据库的类。例如,他定义了类Album: using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MvcMusicStore.Models { public class Album { public int AlbumId {

在学习ASP.NET的过程中,我将遵循以下有关ASP.NET MVC4的教程:

作者准备创建数据库并将其实例放入该数据库的类。例如,他定义了类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
。这是什么意思?据我所知,关系数据库保存ID而不是引用。因此,我们应该只保留ID。

引用属性的目的是允许实体框架显式或隐式加载该引用的关联数据(延迟加载)。使用“引用”属性,可以执行以下操作:

album.Genre.Name;
获取流派的名称(假设它有一个名为
name
)的属性)。但是,如果没有引用,您必须执行以下操作:

var genre = context.Genres.Find(album.GenreId);
genre.Name;
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
    }
}
然而,真正的力量来自组合查询的能力。如果您使用引用属性并提取相册,如:

context.Albums.Include("Genre").Find(albumId);
然后,当您访问类似于
album.Genre.Name
的属性时,不会发出进一步的查询。实体框架在幕后进行了连接,并一次加载了所有数据。而如果没有reference属性,则必须发出两个查询才能到达这里。当考虑参考属性层时,这更为强大。例如,假设您的
Artist
对象也有一个名为
Tour
的类的引用属性,假设每个
Tour
都有一个集合导航属性,指向
Show
,这将是该巡演中的一个单独节目。然后你可以做:

context.Albums.Include("Artist.Tours.Shows").Find(albumId);
同时,不仅要查询专辑和艺术家,还要查询这些艺术家的所有巡演以及每个巡演中的所有演出。虽然这是一个很大的查询,但它是一个单一的查询——这是重要的部分。如果没有这些引用属性,则必须执行以下操作:

var genre = context.Genres.Find(album.GenreId);
genre.Name;
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
    }
}
您现在发出大量查询来获取所需的数据,而您可以只使用一个带有引用属性的查询