2013-08-02 10 views
6

私はEntity Framework 5とMVC 4を使用していますが、.NET 4.5ではCode Firstマイグレーションを使用しています。私は1対0の関係で2つのエンティティの間に外部キーを持っています。ジョガーのためのレコードを作成しようとすると、すべてが爆発する。 dbo.Joggerが UserIdを外部キーに割り当てる= null

  • 未処理の例外...ないメタデータが存在しない

    • 外部キーがnull参照
    • です:私はどちらかのエラーメッセージを取得します。

    私がEF Viewerを実行すると、ナビゲーション関係は完璧です。 Fluent APIコードは現時点では使用されていません。

    ユーザークラス

     [Key] 
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
        public int UserId { get; set; } 
        public string UserName { get; set; } 
    
        // Other properties 
    
        public int? JoggerId { get; set; } 
        public virtual Jogger Jogger { get; set; } 
    

    ジョガークラス

    [ForeignKey("UserId")] 
        public int JoggerId { get; set; } 
    
        public virtual UserProfile UserId { get; set; } 
    

    JoggerControllerが発生した場合には、GETとPOSTメソッドのコードを生成します。

    // GET: /Jogger/Create 
    
        public ActionResult Create() 
        { 
         ViewBag.JoggerId = new SelectList(db.UserProfiles, "UserId", "UserName"); 
         return View(); 
        } 
    
        // 
        // POST: /Jogger/Create 
    
        [HttpPost] 
        [ValidateAntiForgeryToken] 
        public ActionResult Create(Jogger jogger) 
        { 
    
    
    
         if (ModelState.IsValid) 
         { 
          db.Jogger.Add(jogger); 
          db.SaveChanges(); 
          return RedirectToAction("Index"); 
         } 
    
         ViewBag.JoggerId = new SelectList(db.UserProfiles, "UserId", "UserName", jogger.JoggerId); 
         return View(jogger); 
        } 
    

    ジョガー/作成ビューには、生成されたコードに従ってJoggerIdまたはUserIdのフィールドはありません。

    通常、出力でJoggerId = 0およびUserId = nullが表示されるコードの(ModelState.IsValid)部分でエラーが発生します。

    Contoso Universityチュートリアルのasp.netのWebサイトでこの動作が見られませんでした。私はMSDN Learn EFサイトも見てきました。私はこの問題を解決できないようです。あなたのアドバイスは高く評価されます。ここで

  • 答えて

    3

    多くの試行錯誤の後、私は割り当てるために働く方法を見つけました外部キー値。

    最初に、私の関係が正しく設定されていませんでした。UserProfileクラスはpublic intを必要としませんでしたか?ナビゲーションプロパティを表すGolferId。次のように最終的なクラスが見えた:

    のUserProfile

    [Key] 
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
        public int UserId { get; set; } 
        public string UserName { get; set; } 
    
        // Navigation properties 
        public virtual Jogger Jogger { get; set; } 
    

    ジョガークラス

    [Key] 
    [ForeignKey("UserId")] 
    public int JoggerId { get; set; } 
    
    public string Pronation {get; set;} 
    
    public virtual UserProfile UserId { get; set; } 
    

    このセットアップ任意の流暢APIコードを必要とせず、正しい関係を。

    ForeignKey値を割り当てるにはちょっとトリッキーでしたが、これよりも多くの方法があります。

    1. (id = 0)を定義する他のスキャフォールディングの代わりに、私はFormCollectionを使用しました。また、[Bind(Include = "field1、field2、field3")]を使用して、正しいフィールドが確実に転記されるようにすることもできます。
    2. FormCollectionは、私は、例えば、他のフィールドを参照し、保存することができますUser.Identity.Name
    3. を利用してログインしているユーザーのユーザーIDを取得するための長い道のりがあります回内

      [HttpPost] 
      [ValidateAntiForgeryToken] 
      public ActionResult Create(FormCollection values) 
      { 
      
          var jogger = new Jogger(); 
          TryUpdateModel(jogger); 
      
          var context = new TestContext(); 
          var userqq = User.Identity.Name; 
          var user = context.UserProfiles.SingleOrDefault(u => u.UserName == userqq); 
      
          if (ModelState.IsValid) 
          { 
      
            jogger.JoggerId = user.UserId; 
            jogger.Pronation = values["Pronation"]; 
      
      
            db.Joggers.Add(jogger); 
            db.SaveChanges(); 
            return View(); 
      
      
          } 
           ViewBag.JoggerId = new SelectList(db.UserProfiles, "UserId", "UserName", jogger.JoggerId); 
           return View(jogger); 
      
      } 
      

    これは、すべてではきれいではありませんでしたが、それは作業を行います。 @Moeriが私に正しい方向を向けるように感謝します。

    1

    はあなたのエラーです:

    public virtual UserProfile UserId { get; set; } 
    

    Entity Frameworkのコードファーストは、そのうちの一つは、名前ベースの規則であること、規則で動作します。これは、プロパティ "UserId"がある場合、テーブル "User"を検索し、そのテーブルの外部キーとして設定することを意味します。 ナビゲーションプロパティに外部キープロパティに通常使用されている名前を付けたので、爆発すると思います。

    作業の正しい方法は次のようになります。

    public virtual int? UserId { get; set; } 
    public virtual User User { get; set; } 
    

    あなたはあなたの財産は「UserProfileId」と呼ばれるようにしたい場合は、Entity Frameworkのを許可する「のForeignKey」属性や流暢な設定構文を使用する必要がありますこれが外部キーである知っている:

    public virtual int? UserProfileId{ get; set; } 
    
    [ForeignKey("UserProfileId") 
    public virtual User User { get; set; } 
    

    または流暢な構文で(あなたのコンテキストのOnModelCreating方法でこれを書き込み、またはEntityTypeConfigurationから継承別のクラスで):

    編集:あなたのUserテーブルが実際にUserProfileと呼ばれていることに気がつきました。これは、私の応答の後半部分を表現するものです。それにもかかわらず、私はそれが教育的なことができるようにそのまま残します。

    +1

    ありがとう@Moeri前半でpublic virtual UserProfile UserProfileを使用して提案した変更を行いましたが、(Model is Valid)で同じエラーが表示されました。追加が失敗すると、JoggerIdは0に設定されます。 – Springbokkie

    +0

    JoggerテーブルにUser IDのデータベース値を手動で入力しても、手動で入力されたJoggerレコードを表示するだけでモデルを強制終了するため、根本的に私の解決策に問題があるのだろうかと思います。 – Springbokkie

    2

    このエラーは、データベースベースのモデルです。 エンティティフレームワークコードファーストでは、1対1の関係の設定が常に必要です。 Code Firstでは、これらの状況でどのクラスが従属クラスであるかを判断できません。あなたのジョガーのクラスで

    の1-プロパティを追加します。

    public virtual User User { get; set; } 
    

    2 - あなたのOnModelCreatingメソッドでは、追加:

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
         // One to One relationship 
         modelBuilder.Entity<User>() 
             .HasOptional(t => t.Jogger) 
             .WithOptionalDependent(m => m.User); 
    } 
    
    +0

    ありがとうございます。私はこのように構築しようとしましたが、EFビューアでエラーが発生しました。 UserIdからJoggerIdを割り当てる方法を見つけることができました。 – Springbokkie