3

これで再び髪を引き裂く... 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;

}

私は 2、3 日間これに打ちのめされてきました。もし誰かが私の間違いを見つけることができれば、私は最も感謝しています!

ありがとう、ピーター

更新:この投稿を読んで、何かをプロパティではなくフィールドとして宣言したため、骨の折れる間違いを1つ見つけました...しかし、今では理解できない別の例外が発生します:

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 はプロファイルで宣言されたプロパティであるため、これは私を混乱させます...?

2 番目の更新:

私は例外を理解していますが、(内部例外の詳細がないため)どこから来たのかを判断できません。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」が両方のテーブルの外部キーであることに固執しています(ユーザーテーブルでは、プロファイルテーブルの外部キーであり、プロファイルテーブルでは、ユーザーテーブルの外部キーです。)ある種の循環性の問題があった場合に備えて、両方に .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 の初心者であることを知っていますが、問題を見つけることができません (まあ、とにかくまだ...)

再度、感謝します。

4

2 に答える 2

14
public User User;

フィールドではなくプロパティにする必要があります-他のすべてのように:)

public User User { get; set; }

すべてのvirtualナビゲーション プロパティをvirtual

UPDATEについて編集する

例外は、ナビゲーション プロパティ について話しUserId、それが「有効なナビゲーション プロパティ」ではないことを訴えます。実際、有効なナビゲーション プロパティではありません。この例外は、メソッドでUserId(の代わりにUser)を使用した可能性があることを示していますWithRequired。あなたはそれを詳しく見ていくべきです。

于 2013-10-07T15:10:01.330 に答える
0

ピーター、2 つの「UserId」列の問題に関して、あなたはそれらが両方とも外部キーであると言いました。あなたが正しいとは思いません。はUser.UserIdでマークされており、そのようにマークされているクラス[Key]で唯一のものです。Userテーブルのプライマリ ID である必要がありUserます。クラスでは、 と のProfile両方がUserIdありFunctionalAreaます[Key]。これは、テーブルに結合主キーがあり、そのうちの 1 つがテーブルの列Profileへの外部キーであることを意味します。UserUserId

そのデザインはまったく問題ありません。ただし、レコードが親であるレコードとの間Userに関係を持たせるには、テーブルの 2 つの主キーを参照するテーブルに 2 つの列が必要であり、それらの列のどちらもテーブルの列ではない可能性があります。どちらのレコードも作成できない循環依存関係になります。ProfileProfileUserProfileUserIdUser

User要するに、とProfileテーブルの間に 2 つのリレーションシップはなく、1 つだけです。Profile_mapクラスから次のブロックを削除します。

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

それはそれを正しく修正するはずです!;)

于 2013-10-07T21:59:09.387 に答える