What does it mean for an entity type to be in “shadow state”?

試著忘記壹切 提交于 2019-12-10 14:24:07

问题


In my ASP.NET Core 1.0, MVC6, EF7 web application, I'm adding a migration that adds a new related table (& corresponding model). I have the following model snapshot:

[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; }
}

ApplicationUser:

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; }
}

When I attempt to update the database, dnx gives me the following error:

The navigation property 'Manager' cannot be added to the entity type 'Team' because the entity type is defined in shadow state and navigations properties cannot be added to shadow state.

What does it mean for an entity type to be in "shadow state"? Is there a way around this?


回答1:


The EF documentation explains what a shadow property is:

You can use the Fluent API to configure shadow properties. Once you have called the string overload of Property - A.C. you can chain any of the configuration calls you would for other properties.

If the name supplied to the Property method (Property<...>("...") - A.C.) matches the name of an existing property - A.C. (a shadow property or one defined on the entity class), then the code will configure that existing property rather than introducing a new shadow property.

So, I guess an entity is in shadow state when the entity is having at least one shadow property.

This means that you should be very careful when using the string overload of Property<...>("..."), since this may introduce shadow properties even if you do not need them. As a result, when the database needs to be created EF complains that no CLR type exists for the entity in shadow state.

Using nameof() instead of plain strings may help. Thus the overload would look like Property<...>(nameof(...)) which is safer.

And finally, to get closer to the point shadow properties are introduced to handle relationships between entities. The following explains it:

By convention, shadow properties are only created when a relationship is discovered but no foreign key property is found in the dependent entity class. In this case, a shadow foreign key property will be introduced.




回答2:


The issue was actually related to my ApplicationDbContext class. Instead of manually creating the migration and updating the ApplicationDbContextModelSnapshot, I have added to 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");
    }
}

and then I learned how to generate migrations using dnx ef migrations add [migration name].

In this way, I successfully got my site working, but I'd still like to know what "shadow state" is, if someone can answer.




回答3:


Did you read https://github.com/aspnet/EntityFramework/issues/2801 ? You are using not stable version of the Entity Framework, try to recreate the database. You should consider to move to the EF 6.x if your application is going to the production environment.



来源:https://stackoverflow.com/questions/35074941/what-does-it-mean-for-an-entity-type-to-be-in-shadow-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!