实体框架认为存在不存在的列



我有2个表:

InboxEvent
    int Id
    Visitor Owner
    [ForeignKey("Owner")]
    string OwnerId
    Visitor CausingUser
    [ForeignKey("CausingUser")]
    string CausingUserId
Visitor
    string Id

所有者和引起访问者表都指向访问者表,但是在SQL Server Entity中,框架已经进入并创建了inboxevent表,例如:

FK OwnerId
FK CausingUserId
FK Visitor_Id

,果然,它发明了一列:

NVarChar(128) Visitor_Id

好吧...奇怪...很简单,我会用手动迁移杀死流浪柱:

public partial class KillInboxEventVisitor_Id : DbMigration
{
    public override void Up()
    {
        DropForeignKey("dbo.InboxEvent", "Visitor_Id", "dbo.AspNetUsers");
        DropIndex("dbo.InboxEvent", "IX_Visitor_Id");
        DropColumn("dbo.InboxEvent", "Visitor_Id");
    }

太好了,它消失了!现在...每次我尝试让EF保存一个inboxevent:

db.InboxEvents.Add(new InboxEvent {...
await db.SaveChangesAsync();

ef用

爆炸

SqlException: Invalid column name 'Visitor_Id'.

我如何告诉基础的EF模型此想象的列不存在?

编辑/更多信息

这是普通的实体框架6.x,带有ASP.NET/OWIN身份框架,而不是较新的EF7/Core。

我被要求展示完整的课程。很高兴,但是,抓住您的屁股,它们在上面缩写是有原因的:

public class InboxEvent : IOwnerId
{
    public int Id { get; set; }
    [Index("IX_UserRead", 2)]
    public DateTime CreatedOn { get; set; }
    /// <summary>
    /// The user whose Inbox this event is deposited into.
    /// </summary>
    [ForeignKey("Owner"), Required]
    [MaxLength(128)]
    [Index("IX_UserRead", 0), Index]
    public string OwnerId { get; set; }
    public Visitor Owner { get; set; }
    [Index("IX_EventType_RelatedId1", 0)]
    public InboxEventType EventType { get; set; }
    public Posting.PostCore Post { get; set; }
    [ForeignKey("Post")]
    public int? PostId { get; set; }
    public Posting.PostReply Reply { get; set; }
    [ForeignKey("Reply")]
    public int? ReplyId { get; set; }
    [Index("IX_UserRead", 1)]
    public bool IsRead { get; set; }
    /// <summary>
    /// The user, if any, that caused/triggered this event. For example if A upvotes B, this is A, and B is Visitor.
    /// </summary>
    [ForeignKey("CausingUser")]
    [MaxLength(128)]
    public string CausingUserId { get; set; }
    public Visitor CausingUser { get; set; }

    [Index]
    [Index("IX_EventType_RelatedId1", 1)]
    public int RelatedId1 { get; set; }
    public int RelatedId2 { get; set; }

    public InboxEvent()
    {
        CreatedOn = DateTime.UtcNow;
    }
}
public class Visitor : IdentityUser<string, LoginIdentity, StandardUserRole, IdentityUserClaim>, IVisitor
{
    [MaxLength(22), Column(TypeName = "Char"), Index]
    public string Uid { get; set; }
    [MaxLength(300), Index]
    public string FirstName { get; set; }
    [MaxLength(300), Index]
    public string LastName { get; set; }
    public DateTime CreatedOn { get; set; }
    public DateTime MemberOn { get; set; }
    
    public int Invites { get; set; }
    public int Score { get; set; }
    public bool ShouldReceiveReplyNotifications { get; set; }
    public DateTime LastEmailNotified { get; set; }
    [MaxLength(100), Column(TypeName="VarChar")]
    public string ProfilePic { get; set; }
    public ICollection<UserPhoto> UserPhotos { get; set; }
    public StaticImage StaticImage { get; set; }

    // BioViewModel
    [MaxLength(100)]
    public string Nickname { get; set; }
    [MaxLength(400)]    // TODO Normalize
    public string Disciplines { get; set; }
    [MaxLength(1000)]
    public string MissionStatement { get; set; }
    [MaxLength(100)]
    public string Tagline { get; set; }
    // SkillsViewModel
    [MaxLength(400)]
    public string SkillsKnown { get; set; }
    [MaxLength(400)]
    public string SkillsToLearn { get; set; }
    // PrefsViewModel
    [MaxLength(10)]
    public string PhoneCountryCode { get; set; }
    //[MaxLength(20)]
    //public string PhoneNumber { get; set; }   // Already in base OWIN User model
    public ChatService ChatService { get; set; }
    [MaxLength(100)]
    public string ChatHandle { get; set; }
    public byte PrefIpOpenness { get; set; }
    public byte PrefNonProfit { get; set; }
    public byte PrefMature { get; set; }
    public PrivacyLevel PrivacyNameCountryCity { get; set; }
    public PrivacyLevel PrivacyBio { get; set; }
    public PrivacyLevel PrivacySites { get; set; }
    public PrivacyLevel PrivacyCompanies { get; set; }
    public PrivacyLevel PrivacySkills { get; set; }
    public PrivacyLevel PrivacyContactInfo { get; set; }
    public PrivacyLevel PrivacyCollabPrefs { get; set; }
    public bool WantMonthlyNewsletter { get; set; }
    public bool WantToMentor { get; set; }
    public bool WantToVetProjects { get; set; }
    public bool WantToReviewProjects { get; set; }
    public bool WantToGiveFeedback { get; set; }
    // CommitmentViewModel
    public CommitmentChoice CommitmentChoice { get; set; }
    [MaxLength(1000)]
    public string CommitmentText { get; set; }

    public ICollection<CountryZip> CountryZips { get; set; }
    public ICollection<Org> Orgs { get; set; }
    public ICollection<UserSite> UserSites { get; set; }

    public ICollection<DraftData> Drafts { get; set; }
    public ICollection<Visitor_Team> Teams { get; set; }
    public ICollection<InboxEvent> Inbox { get; set; }
    public ICollection<SubscribedPost> PostSubscriptions { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<Visitor, string> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }

    public Visitor()
    {
        CreatedOn = (DateTime)SqlDateTime.MinValue;
        MemberOn = (DateTime)SqlDateTime.MinValue;
        LastEmailNotified = (DateTime)SqlDateTime.MinValue;
    }
}

db确实有一个on modelscreating,尽管在这里不太可能相关:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        var entity = modelBuilder.Entity<Visitor>();
        // By default this is nvarchar max? Uh?
        entity.Property(v => v.PhoneNumber).HasMaxLength(20);
    }

VisitorInboxEvent之间有三个关联。您最初显示的两个:

public class InboxEvent : IOwnerId
{
    ...
    [ForeignKey("Owner"), Required]
    public string OwnerId { get; set; }
    public Visitor Owner { get; set; }
    [ForeignKey("CausingUser")]
    public string CausingUserId { get; set; }
    public Visitor CausingUser { get; set; }
    ...
}

和:

public class Visitor : IdentityUser<string, ...
{
    ...
    public ICollection<InboxEvent> Inbox { get; set; }
    ...
}

毫不发能地,EF将假设这些关联彼此独立:它将创建三个FKS,其中Visitor_Id用于后一个关联。

您可能希望InboxEvent.OwnerVisitor.Inbox成为一个关联的两个端,但是EF不知道,这不会猜测。您必须将其显式,例如使用[InverseProperty]属性:

public class InboxEvent : IOwnerId
{
    ...
    [ForeignKey("Owner"), Required]
    public string OwnerId { get; set; }
    [InverseProperty("Inbox")]
    public Visitor Owner { get; set; }
    ...
}

相关内容

  • 没有找到相关文章

最新更新