【问题标题】:What does it mean for an entity type to be in "shadow state"?实体类型处于“影子状态”意味着什么?
【发布时间】:2022-02-15 05:19:04
【问题描述】:

在我的 ASP.NET Core 1.0、MVC6、EF7 Web 应用程序中,我添加了一个迁移,该迁移添加了一个新的相关表(和相应的模型)。我有以下模型快照:

[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
    protected override void BuildModel(ModelBuilder modelBuilder)
    {
        modelBuilder
            .HasAnnotation("ProductVersion", "7.0.0-rc1-16348")
            .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

        modelBuilder.Entity("Salesboost.Models.ApplicationUser", b =>
        {
            b.Property<string>("Id");
            b.Property<int?>("TeamId");
            b.HasKey("Id");
            // -- <unrelated fields snipped> --
        });

        // -- <snipped> --

        modelBuilder.Entity("Team", b =>
        {
            b.Property<int>("Id").ValueGeneratedOnAdd();
            b.Property<string>("Name").IsRequired();
            b.Property<string>("ManagerId").IsRequired();
            b.HasKey("Id");
        });

        modelBuilder.Entity("Team", b =>
        {
            b.HasOne("ApplicationUser", "Manager")
                .WithOne("TeamManaging")
                .HasForeignKey("ManagerId");
        });
    }
}

Team.cs:

public class Team
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string ManagerId { get; set; }

    public virtual ApplicationUser Manager { get; set; }
    public virtual ICollection<ApplicationUser> Members { get; set; }
}

应用用户:

public class ApplicationUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser
{
    public int? TeamId { get; set; }

    public virtual Team Team { get; set; }
    public virtual Team TeamManaging { get; set; }
}

当我尝试更新数据库时,dnx 给了我以下错误:

导航属性“经理”不能添加到实体类型“团队”,因为实体类型是在影子状态中定义的,导航属性不能添加到影子状态。

实体类型处于“影子状态”意味着什么?有没有办法解决这个问题?

【问题讨论】:

  • 你能把你ApplicationUser的modelbuilder包括进来吗?
  • Alexander,我已经添加了模型构建器。

标签: asp.net-mvc entity-framework asp.net-core-1.0


【解决方案1】:

EF documentation 解释了什么是影子属性:

您可以使用 Fluent API 来配置阴影属性。一旦您调用了Property 的字符串重载 - A.C.,您就可以链接您对其他属性的任何配置调用。

如果 提供给 Property 方法的名称 (Property&lt;...&gt;("...") - A.C.) 与现有属性的名称匹配 - A.C.(影子属性或在实体类上定义的属性),则代码将配置该现有属性,而不是引入新的影子属性。

所以,我猜当实体具有至少一个影子属性时,该实体处于影子状态。

这意味着在使用Property&lt;...&gt;("...") 的字符串重载时应该非常小心,因为即使您不需要它们也可能会引入影子属性。结果,当需要创建数据库时,EF 抱怨影子状态的实体不存在 CLR 类型。

使用nameof() 代替纯字符串可能会有所帮助。因此重载看起来像Property&lt;...&gt;(nameof(...)),这样更安全。

最后,为了更接近点阴影,引入了属性来处理实体之间的关系。 下面解释一下:

按照惯例,只有在发现关系但在依赖实体类中没有找到外键属性时才会创建影子属性。在这种情况下,将引入影子外键属性。

【讨论】:

    【解决方案2】:

    这个问题实际上与我的ApplicationDbContext 课程有关。我没有手动创建迁移和更新ApplicationDbContextModelSnapshot,而是添加到ApplicationDbContext:

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        // -- <snipped> --
        public DbSet<Team> Teams { get; set; }
        public ApplicationUser Manager { get; set; }
        public ApplicationUser Members { get; set; }
    
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
    
            builder.Entity<Team>().HasOne(typeof(ApplicationUser), "Manager")
                .WithOne("TeamManaging")
                .HasForeignKey(typeof(Team), "ManagerId")
                .HasPrincipalKey(typeof(ApplicationUser), "Id");
            builder.Entity<ApplicationUser>().HasOne(typeof(Team), "Team")
                .WithMany("Members")
                .HasForeignKey("TeamId");
        }
    }
    

    然后我学会了如何使用 dnx ef migrations add [migration name] 生成迁移。

    通过这种方式,我成功地让我的网站正常工作,但我仍然想知道“影子状态”是什么,如果有人可以回答的话。

    【讨论】:

    • infoq.com/news/2015/08/Shadow-Properties 影子属性是类本身不存在的字段,但被实体框架视为存在。他们可以参与查询、创建/更新操作和数据库迁移。
    • 基本,链接后面的文章是描述属性。我问的是实体类型。我的“团队”实体类型不是影子;是真的。有一个实际的数据库表,其中包含支持它的实际数据库字段。 “团队”处于“影子状态”是什么意思?
    • 我的猜测是你映射了两次字段,并且这些字段在代理类中相互遮蔽(例如,创建一个动态的TeamId 隐藏了你的显式TeamId),但没有重新创建情况以确定,这只是一个猜测。这绝对是阴影方法的非 EF7 含义。
    【解决方案3】:

    在我的例子中,当我在模型中删除外键但忘记在 ApplicationDbContext 构建模型中删除它时出现此错误。

    【讨论】:

      【解决方案4】:

      你读过https://github.com/aspnet/EntityFramework/issues/2801 吗? 您使用的实体框架版本不稳定,请尝试重新创建数据库。 如果您的应用程序要进入生产环境,您应该考虑迁移到 EF 6.x。

      【讨论】:

      • 抛开 EF7 的就绪性不谈,你知道实体类型处于“影子状态”意味着什么吗?谢谢你的链接。我花了很多时间在谷歌上搜索这个问题,但从未遇到过。 (尽管令人沮丧的是该页面上的答案没有回答相同的问题。)
      猜你喜欢
      • 2018-10-26
      • 1970-01-01
      • 2013-01-16
      • 2017-09-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 2017-06-22
      • 1970-01-01
      相关资源
      最近更新 更多