【问题标题】:Entity Framework 5 code first cannot get model to workEntity Framework 5 代码首先无法让模型工作
【发布时间】:2013-10-07 14:54:37
【问题描述】:

在这个问题上再次扯出我的头发......使用 EF 5 Code First,在代码中构建模型 - 编译,所以它在语法上是正确的,但是当代码构建模型时我得到一个异常。这是实体类(我也有 vaidation 属性,但为了便于阅读,在这里删除了它们):

[Table("USERS")]
public class User : IPEntity
{
    #region Constructor (needs to initialize list objects for related entities)

    public User()
    {
        this.Profiles = new List<Profile>();
        this.ProfileDivs = new List<ProfileDiv>();
        this.ProfileDepts = new List<ProfileDept>();
    }

    #endregion

    #region Entity properties and validation attributes

    [Key]
    public long UserId { get; set; }

    public long PclientId { get; set; }

    public string UserName { get; set; }

    public string UserDescription { get; set; }

    public long? EmpId { get; set; }

    public string MustChangePassword { get; set; }

    public long? FailedLogins { get; set; }

    public DateTime? LastLogin { get; set; }

    public long? SequenceNumber { get; set; }

    public string AllDivs { get; set; }

    public string AllDepts { get; set; }

    public string UserRole { get; set; }

    public DateTime? BeginSupport { get; set; }

    public DateTime? EndSupport { get; set; }

    public string OneTimeAccess { get; set; }

    public long? ClonedFromUser { get; set; }

    public string Email { get; set; }

    public string ResetEmail { get; set; }

    public DateTime? ResetTimeout { get; set; }

    public long? ChallengeFailures { get; set; }

    public string PermUserRole { get; set; }

    public DateTime? PasswordChangedDate { get; set; }

    public virtual ICollection<Profile> Profiles { get; set; }

    public virtual ICollection<ProfileDiv> ProfileDivs { get; set; }

    public virtual ICollection<ProfileDept> ProfileDepts { get; set; }

    public virtual WorkSession WorkSession { get; set; }

}

模型构建器类是:

public class User_Map : EntityTypeConfiguration<User>
{
    public User_Map()
    {
        this.ToTable("USERS");

        this.HasKey(t => new { t.UserId });

        this.Property(t => t.UserId)
            .HasColumnName("USER_ID")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
            .IsRequired();

        this.Property(t => t.UserName)
            .HasColumnName("USERNAME")
            .IsRequired()
            .HasMaxLength(25);

        this.Property(t => t.PclientId)
            .HasColumnName("PCLIENT_ID");

        this.Property(t => t.EmpId)
            .HasColumnName("EMP_ID");

        this.Property(t => t.MustChangePassword)
            .HasColumnName("MUST_CHANGE_PASSWORD")
            .HasMaxLength(1);

        this.Property(t => t.UserDescription)
            .HasColumnName("USER_DESCRIPTION")
            .HasMaxLength(80);

        this.Property(t => t.FailedLogins)
            .HasColumnName("FAILED_LOGINS");

        this.Property(t => t.LastLogin)
            .HasColumnName("LAST_LOGIN");

        this.Property(t => t.SequenceNumber)
            .HasColumnName("SEQUENCE_NUMBER");

        this.Property(t => t.AllDivs)
            .HasColumnName("ALL_DIVS")
            .HasMaxLength(1);

        this.Property(t => t.AllDepts)
            .HasColumnName("ALL_DEPTS")
            .HasMaxLength(1);

        this.Property(t => t.UserRole)
            .HasColumnName("USER_ROLE")
            .HasMaxLength(2);

        this.Property(t => t.BeginSupport)
            .HasColumnName("BEGIN_SUPPORT");

        this.Property(t => t.EndSupport)
            .HasColumnName("END_SUPPORT");

        this.Property(t => t.OneTimeAccess)
            .HasColumnName("ONE_TIME_ACCESS")
            .HasMaxLength(1);

        this.Property(t => t.ClonedFromUser)
            .HasColumnName("CLONED_FROM_USER");

        this.Property(t => t.Email)
            .HasColumnName("EMAIL")
            .HasMaxLength(60);

        this.Property(t => t.ResetEmail)
            .HasColumnName("RESET_EMAIL")
            .HasMaxLength(60);

        this.Property(t => t.ResetTimeout)
            .HasColumnName("RESET_TIMEOUT");

        this.Property(t => t.ChallengeFailures)
            .HasColumnName("CHALLENGE_FAILURES");

        this.Property(t => t.PermUserRole)
            .HasColumnName("PERM_USER_ROLE")
            .HasMaxLength(2);

        this.Property(t => t.PasswordChangedDate)
            .HasColumnName("PASSWORD_CHANGED_DATE");

        this.HasOptional(t => t.WorkSession)
            .WithRequired(t => t.User);

        // TODO: This is syntactically correct but model blows up!

        this.HasMany(t => t.Profiles)
            .WithRequired(t => t.User)
            .HasForeignKey(t => t.UserId);

    }
}

当模型构建器类的构造函数执行时,我在上面的行(注释之后)抛出了以下异常:

The expression 't => t.User' is not a valid property expression. 
The expression should represent a property: C#: 't => t.MyProperty'  
VB.Net: 'Function(t) t.MyProperty'.

Profiles 实体非常简单:

[Table("PROFILE")]
public class Profile : IPEntity
{
    [Key, Column(Order = 0)]
    [ForeignKey("UserId")]
    public long UserId { get; set; }

    [Key, Column(Order = 1)]
    public string FunctionalArea { get; set; }

    public int RightsId { get; set; }

    public User User;

}

我已经在这个问题上打了两三天,如果有人能发现我的错误,我将非常感激!

谢谢, 彼得

更新:我在阅读this post 时发现了一个严重的错误,因为我已将某些内容声明为字段而不是属性...但现在我得到了一个我不明白的不同异常:

The navigation property 'UserId' is not a declared property on type 'Profile'. 
Verify that it has not been explicitly excluded from the model and that 
it is a valid navigation property.

这让我很困惑,因为 UserId 是 Profile 上声明的属性...?

第二次更新:

我了解异常,但(因为没有内部异常详细信息)无法确定它来自何处。我将 User_map 类更改为包括:

        this.HasMany(t => t.Profiles)
            .WithRequired(t => t.User)
            .HasForeignKey(t => t.UserId)
            .WillCascadeOnDelete(false);

以及要包含的 Profile_map 类:

        this.HasRequired(t => t.User)
            .WithMany()
            .HasForeignKey(t => t.UserId)
            .WillCascadeOnDelete(false);

因为我必须使用现有的数据库,所以我坚持使用属性“UserId”作为两个表中的外键(在 User 表中,它是 Profiles 表的外键,在 Profiles 表中,它是 User 的外键表。)我将 .WillCascadeOnDelete(false) 添加到两者中,以防出现某种循环问题。就像我说的那样,我无法确定哪个地图正在炸毁,对两个构造函数的调用均无异常通过,只有当上下文中 OnModelCreating 的覆盖退出时才会引发异常。这是覆盖:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        var mbProfile = new Profile_map();
        modelBuilder.Configurations.Add(mbProfile);

        var mbUser = new User_Map();
        modelBuilder.Configurations.Add(mbUser);

        base.OnModelCreating(modelBuilder);
    }

我知道我还是 EF 新手,但我找不到问题(好吧,反正还没有……)

再次感谢。

【问题讨论】:

    标签: c# entity-framework code-first


    【解决方案1】:
    public User User;
    

    应该是一个 property 而不是一个字段 - 像所有其他人一样:)

    public User User { get; set; }
    

    最好使用virtual(以允许延迟加载),因为您已将所有导航属性标记为virtual

    修改更新

    该异常涉及 导航属性 UserId 并抱怨它不是“有效的导航属性”。事实上,它不是一个有效的导航属性。该异常表明您可能在WithRequired 方法中使用了UserId(而不是User)。你应该仔细看看。

    【讨论】:

    • 是的,谢谢,我通过阅读另一个问题发现了这一点,但现在我遇到了另一个更令人困惑的异常......
    • @PeterHowe:看看我上面关于您的后续异常的编辑。
    • 我在另一个编辑中添加了更多细节,希望能揭示一些东西(可能是我做的一些愚蠢的事情......)
    • @PeterHowe:从Profile_Map 中删除this.HasRequired(t =&gt; t.User).... 映射。如果您已经在User_Map 中映射了关系并且它是矛盾的,则不需要它(如果您在User_Map 中有带有参数的HasMany,则不带参数的WithMany() 是错误的)。还要从 Profile 类中删除 [ForeignKey("UserId")]。将其放在UserId 属性上是错误的,如果您已将关系映射到 Fluent API,则这是多余的。
    • 谢谢,我已经解决了这个错误,但还有更多问题,我会尽力解决问题,然后再发布另一个问题!
    【解决方案2】:

    Peter,关于您对两个“UserId”列的问题,您说它们都是外键。我不认为你是正确的。 User.UserId[Key] 标记,它是User 类中唯一一个以这种方式标记的。它必须是 User 表的主 ID。在 Profile 类上,UserIdFunctionalArea 都标有 [Key]。这意味着Profile 表有一个联合主键,其中一个是User 表的UserId 列的外键。

    这个设计非常好。但是,为了在UserProfile 记录之间建立关系,其中Profile 记录是父记录,您必须在User 表上有两列引用Profile 表的两个主键,并且这些列都不能是User 表的UserId 列,否则您将有一个循环依赖关系,无法创建任何一条记录。

    底线是,UserProfile 表之间没有两个关系,只有一个。所以从你的Profile_map 类中删除以下块:

    this.HasRequired(t => t.User)
        .WithMany()
        .HasForeignKey(t => t.UserId)
        .WillCascadeOnDelete(false);
    

    这应该可以解决问题! ;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      相关资源
      最近更新 更多