实体框架核心:DbContext未链接实体

时间:2020-11-03 00:13:08

标签: c# asp.net-core entity-framework-core

我正在尝试将ASP.NET Core 2.2.0与Entity Framework Core一起使用,并且遇到了一些麻烦。

我想显示我拍摄的不同天体(星云,星系等...)的图片列表。

数据应如下所示:

enter image description here

我创建了实体,进行了迁移,并且一切似乎都正常进行。我手动插入了一些数据,因此可以检查插入是否正确。

CelestialObjectType nebuleuse = new CelestialObjectType { Name = "Nébuleuse", Definition = "Nuage interstellaire de gaz et de poussière" };
CelestialObjectType galaxie = new CelestialObjectType { Name = "Galaxie", Definition = "Vaste ensemble d'étoiles et de matière interstellaire dont la cohésion est assurée par la gravitation" };

context.CelestialObjectTypes.Add(nebuleuse);
context.CelestialObjectTypes.Add(galaxie);
 
CelestialCatalog messier = new CelestialCatalog { Name = "Messier" };
CelestialCatalog ngc = new CelestialCatalog { Name = "NGC" };
CelestialCatalog ugc = new CelestialCatalog { Name = "UGC" };

context.CelestialCatalogs.Add(messier);
context.CelestialCatalogs.Add(ngc);
context.CelestialCatalogs.Add(ugc);

CelestialObject m42 = new CelestialObject
        {
            Name = "M42 - Grande nébuleuse d'orion",
            CelestialObjectType = nebuleuse,
            DiscoveryDate = new DateTime(1610, 11, 26)
        };
CelestialObject m81 = new CelestialObject
        {
            Name = "M81 - Galaxie de Bode",
            CelestialObjectType = galaxie,
            DiscoveryDate = new DateTime(1774, 12, 31),
        };
CelestialObject m82 = new CelestialObject
        {
            Name = "M82 - Galaxie du cigare",
            CelestialObjectType = galaxie,
            DiscoveryDate = new DateTime(1774, 12, 31),
        };

context.CelestialObjects.Add(m42);
context.CelestialObjects.Add(m81);
context.CelestialObjects.Add(m82);

CelestialObjectCatalog messier42 = new CelestialObjectCatalog { CelestialCatalog = messier, CelestialObject = m42, Rank=42 };
CelestialObjectCatalog ngc1976 = new CelestialObjectCatalog { CelestialCatalog = ngc, CelestialObject = m42, Rank=1976 };

CelestialObjectCatalog messier81 = new CelestialObjectCatalog { CelestialCatalog = messier, CelestialObject = m81, Rank = 81 };
CelestialObjectCatalog ngc3031 = new CelestialObjectCatalog { CelestialCatalog = ngc, CelestialObject = m81, Rank = 3031 };
CelestialObjectCatalog ugc5318 = new CelestialObjectCatalog { CelestialCatalog = ugc, CelestialObject = m81, Rank = 5318 };

CelestialObjectCatalog messier82 = new CelestialObjectCatalog { CelestialCatalog = messier, CelestialObject = m82, Rank = 82 };
CelestialObjectCatalog ngc3024 = new CelestialObjectCatalog { CelestialCatalog = ngc, CelestialObject = m82, Rank = 3034 };
CelestialObjectCatalog ugc5322 = new CelestialObjectCatalog { CelestialCatalog = ugc, CelestialObject = m82, Rank = 5322 };

context.Add<CelestialObjectCatalog>(messier42);
context.Add<CelestialObjectCatalog>(ngc1976);

context.Add<CelestialObjectCatalog>(messier81);
context.Add<CelestialObjectCatalog>(ngc3031);
context.Add<CelestialObjectCatalog>(ugc5318);

context.Add<CelestialObjectCatalog>(messier82);
context.Add<CelestialObjectCatalog>(ngc3024);
context.Add<CelestialObjectCatalog>(ugc5322);

Picture m42Picture = new Picture
        {
            Date = new DateTime(2019, 12, 26),
            Path = "~/images/Ciel profond/M42 - Nébuleuse d'Orion.jpg",
            SingleExposureTime = new TimeSpan(0, 0, 20),
            RawNumber = 14,
            DarksNumber = 7,
            OffsetsNumber = 8
        };

Picture m8182Picture = new Picture
        {
            Date = new DateTime(2020, 02, 24),
            Path = "~/images/Ciel profond/M81-M82-Galaxies.jpeg",
            SingleExposureTime = new TimeSpan(0, 0, 30),
            RawNumber = 46,
            DarksNumber = 12,
            OffsetsNumber = 15
        };

context.Pictures.Add(m42Picture);
context.Pictures.Add(m8182Picture);

CelestialObjectPicture m42ObjectPicture = new CelestialObjectPicture { CelestialObject = m42, Picture = m42Picture };
CelestialObjectPicture m81ObjectPicture = new CelestialObjectPicture { CelestialObject = m81, Picture = m8182Picture };
CelestialObjectPicture m82ObjectPicture = new CelestialObjectPicture { CelestialObject = m82, Picture = m8182Picture };

context.Add<CelestialObjectPicture>(m42ObjectPicture);
context.Add<CelestialObjectPicture>(m81ObjectPicture);
context.Add<CelestialObjectPicture>(m82ObjectPicture);

context.SaveChanges();

问题从这里开始:当我从数据库加载上下文时,实体似乎没有链接。例如,Pictures没有对链接实体CelestialObjectPictures的引用:

Ce

但是,如果我决定检查CelestialObjectPictures实体,则它确实包含以下值:

enter image description here

然后如果我返回并检查Picture实体(没有代码运行,我仍然在同一个断点处),则出现CelestialObjectPictures

enter image description here

相同的模式出现在所有链接的实体中,这意味着在我手动检查之前:

  • CelestialObject实体没有指向CelestialObjectType(空引用)的链接,也没有CelestialObjectPicturesCelestialObjectCatalogs(空列表)的链接
  • CelestialCatalog实体没有指向CelestialCatalogEntities(空列表)的链接
  • 等...

这是我的DbContext和实体类,请注意,我尝试将DbContext用于:

  • 只是一个DbSet<Pictures>(我在剃须刀页面中使用的顶部对象)
  • 一个DbSet<Pictures>和一个DbSet<CelestialObject>
  • 每个实体(我当前使用的那个)的DbSet

代码:

public class AstroWebSiteDbContext : DbContext
{
        public DbSet<CelestialObjectPicture> CelestialObjectPictures { get; set; }
        public DbSet<CelestialObjectCatalog> CelestialObjectCatalogs { get; set; }
        public DbSet<CelestialObjectType> CelestialObjectTypes { get; set; }

        public DbSet<CelestialCatalog> CelestialCatalogs { get; set; }
        public DbSet<CelestialObject> CelestialObjects { get; set; } 
        public DbSet<Picture> Pictures { get; set; }

        public AstroWebSiteDbContext(DbContextOptions<AstroWebSiteDbContext> options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<CelestialObjectPicture>().
                HasKey(x => new { x.CelestialObjectId, x.PictureId });

            modelBuilder.Entity<CelestialObjectPicture>().
                HasOne(cop => cop.Picture).
                WithMany(pic => pic.CelestialObjectPictures).
                HasForeignKey(cop => cop.PictureId);

            modelBuilder.Entity<CelestialObjectPicture>().
                HasOne(cop => cop.CelestialObject).
                WithMany(co => co.CelestialObjectPictures).
                HasForeignKey(cop => cop.CelestialObjectId);

            modelBuilder.Entity<CelestialObjectCatalog>().
                HasKey(x => new { x.CelestialObjectId, x.CelestialCatalogId });

            modelBuilder.Entity<CelestialObjectCatalog>().
                HasOne(coc => coc.CelestialCatalog).
                WithMany(cc => cc.CelestialObjectCatalogs).
                HasForeignKey(coc => coc.CelestialCatalogId);

            modelBuilder.Entity<CelestialObjectCatalog>().
                HasOne(coc => coc.CelestialObject).
                WithMany(co => co.CelestialObjectCatalogs).
                HasForeignKey(coc => coc.CelestialObjectId);

            base.OnModelCreating(modelBuilder);
        }
}

public class CelestialObjectPicture
{
    [Key]
    public int CelestialObjectId { get; set; }
    [Key]
    public int PictureId { get; set; }

    public CelestialObject CelestialObject { get; set; }
    public Picture Picture { get; set; }
}

public class CelestialObjectCatalog
{
    [Key]
    public int CelestialObjectId { get; set; }
    public CelestialObject CelestialObject { get; set; }

    [Key]
    public int CelestialCatalogId { get; set; }
    public CelestialCatalog CelestialCatalog { get; set; }

    public int Rank { get; set; }
}

public class CelestialObject
{
    [Key]
    public int CelestialObjectId { get; set; }

    public string Name { get; set; }

    public CelestialObjectType CelestialObjectType { get; set; }
    public DateTime DiscoveryDate { get; set; }

    public List<CelestialObjectPicture> CelestialObjectPictures { get; set; } = new List<CelestialObjectPicture>();

    public List<CelestialObjectCatalog> CelestialObjectCatalogs { get; set; } = new List<CelestialObjectCatalog>();
}

public class CelestialCatalog
{
    [Key]
    public int CelestialCatalogId { get; set; }

    public string Name { get; set; }

    public List<CelestialObjectCatalog> CelestialObjectCatalogs { get; set; } = new List<CelestialObjectCatalog>();
}

我可以肯定我遗漏了一些明显的东西,但是可惜,我找不到与该问题有关的任何东西。任何帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

您已经在调试器中有效地执行了以下操作;

context.Pictures.ToList(); // => select * from Pictures;
context.CelestialObjectPictures.ToList(); // => select * from CelestialObjectPictures;
context.Pictures.ToList(); // => select * from Pictures;

每个DbSet的每个枚举都会将该对象列表加载到变更跟踪器中。变更跟踪器中已经存在的任何其他已知对象将链接在一起。数据库可能非常庞大,您很少要加载所有内容。

如果要一次加载所有内容,则应运行自己的查询以具体化您感兴趣的数据对象。包括您还希望同时加载的任何其他外键;

var objects = await context.CelestialObjects
    .Include(o => o.CelestialObjectsPictures)
        .ThenInclude(c => c.Pictures)
    .ToListAsync();

如果您不将其包含在查询中,则不会将其加载到内存中。