2013-08-02 29 views
6

Tôi đang sử dụng Entity Framework 5 và MVC 4, với .NET 4.5 sử dụng di chuyển Code First. Tôi có chìa khóa nước ngoài giữa hai thực thể trong mối quan hệ 1 hoặc 0 hoặc 1. Khi tôi cố gắng để tạo ra kỷ lục cho tất cả mọi thứ Jogger thổi lên. Tôi nhận được thông báo lỗi mà là một trong hai:Chỉ định UserId cho khóa ngoài = null

  • Ngoại Key là một tham chiếu null
  • dbo.Jogger không tồn tại
  • Unhandled ngoại lệ ... không có siêu dữ liệu.

Khi tôi chạy Trình xem EF, các mối quan hệ điều hướng là hoàn hảo. Không có mã API Fluent nào được sử dụng tại thời điểm này.

tài Lớp

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

Jogger Lớp

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

    public virtual UserProfile UserId { get; set; } 

Khi JoggerController được tạo ra nó tạo ra mã này cho Nhận và phương pháp mới gởi:

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

Trong giao diện Jogger/Create không có trường cho JoggerId hoặc UserId theo mã được tạo ra.

Thông thường nó không thành công trên phần (ModelState.IsValid) mã nơi Đầu ra hiển thị JoggerId = 0 và UserId = null.

Tôi chưa thấy hành vi này trên hướng dẫn của Đại học Contoso trên trang web của asp.net và tôi cũng đã xem trang web MSDN Learn EF. Tôi không thể giải quyết vấn đề này. Lời khuyên của bạn được đánh giá cao.

Trả lời

3

Sau nhiều thử và sai tôi tìm thấy một cách mà làm việc để gán Khóa ngoại một giá trị.

Thứ nhất, mối quan hệ của tôi đã được thiết lập không chính xác: Lớp UserProfile không cần int công cộng? GolferId đại diện cho một thuộc tính điều hướng. lớp học thức trông như sau:

UserProfile

[Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 
    public string UserName { get; set; } 

    // Navigation properties 
    public virtual Jogger Jogger { get; set; } 

Jogger Lớp

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

public string Pronation {get; set;} 

public virtual UserProfile UserId { get; set; } 

thiết lập mối quan hệ này đúng mà không cần bất kỳ mã API thạo.

Để gán giá trị ForeignKey phức tạp hơn một chút và tôi chắc chắn có nhiều cách tốt hơn để thực hiện điều này.

  1. Thay vì phương pháp giàn giáo khác để xác định (id = 0), tôi đã sử dụng một FormCollection. Bạn cũng có thể sử dụng [Bind (Include = "field1, field2, field3")] để đảm bảo rằng các trường chính xác đang được đăng.
  2. Có một chặng đường dài để truy cập UserId của Người dùng đã đăng nhập, sử dụng User.Identity.Name
  3. Việc định dạng FormCollection cho phép tôi tham khảo và lưu các trường khác, ví dụ: Quay sấp

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

Đây không phải là khá ở tất cả nhưng nó làm việc. Nhờ @Moeri đã chỉ cho tôi đúng hướng.

1

Đây là lỗi của bạn:

public virtual UserProfile UserId { get; set; } 

Entity Framework Mã đầu tiên làm việc với các công ước, một trong số đó là tên dựa trên công ước. Điều đó có nghĩa rằng nếu bạn có một thuộc tính "UserId", nó sẽ tìm một bảng "User" và cấu hình nó như là một khóa ngoài cho bảng đó. Tôi nghĩ rằng nó bị thổi phồng bởi vì bạn đã cho thuộc tính điều hướng của bạn một tên được sử dụng thông thường cho một thuộc tính khóa ngoài.

Cách đúng đắn về lao động sẽ là:

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

Nếu bạn muốn tài sản của bạn được gọi là "UserProfileId", bạn sẽ phải sử dụng "ForeignKey" thuộc tính hoặc các cú pháp cấu hình thông thạo để cho Entity Framework biết đây là một chìa khóa nước ngoài:

public virtual int? UserProfileId{ get; set; } 

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

hoặc với cú pháp thông thạo (bạn viết những dòng này trong phương pháp OnModelCreating của Bối cảnh của bạn, hoặc trong một lớp học riêng biệt mà được thừa hưởng từ EntityTypeConfiguration):

012.
HasRequired(j => j.User).WithMany().HasForeignKey(i => i.UserProfileId) 

Chỉnh sửa: Tôi vừa mới nhận thấy bảng Người dùng của bạn thực sự được gọi là UserProfile, loại sắp xếp hiển thị nửa sau của cuộc tranh luận phản hồi của tôi. Tuy nhiên tôi sẽ để nó vì nó có thể là giáo dục.

+1

Cảm ơn @Moeri Tôi đã thực hiện các thay đổi bạn đã đề xuất trong nửa đầu sử dụng PublicProfile UserProfile UserProfile) nhưng vẫn cho tôi lỗi tương tự trên (Model is Valid). JoggerId được đặt thành 0 khi Add không thành công. – Springbokkie

+0

Tôi tự hỏi nếu có điều gì đó về cơ bản thiếu sót với giải pháp của tôi vì ngay cả khi tôi nhập thủ công các giá trị cơ sở dữ liệu cho Id người dùng trong bảng Jogger nó vẫn giết mô hình chỉ xem bản ghi Jogger được nhập theo cách thủ công. – Springbokkie

2

Lỗi trong mô hình cơ sở dữ liệu. Mã khung thực thể Đầu tiên sẽ luôn yêu cầu cấu hình cho các mối quan hệ một-một. Mã đầu tiên không thể xác định lớp nào là người phụ thuộc trong các tình huống này.

1- Trong lớp Jogger bạn thêm tài sản:

public virtual User User { get; set; } 

2 - Trong phương pháp OnModelCreating của bạn thêm:

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

Cảm ơn Aguedo. Tôi đã cố gắng để xây dựng nó như thế này nhưng có một lỗi trên người xem EF. Tôi quản lý để tìm một cách để chỉ định JoggerId từ UserId. – Springbokkie

Các vấn đề liên quan