2011-08-08 27 views
8

Tôi đã dành vài ngày ngay bây giờ, cố gắng giải quyết vấn đề này. Trong khi thực hiện một dự án đơn giản để minh họa cho vấn đề của tôi, tôi tình cờ tìm ra một giải pháp khả thi. Vì vậy, đây là một câu hỏi gấp đôi.Khuôn khổ thực thể, mã Mô hình đầu tiên và tham chiếu chu kỳ

Nhưng trước tiên, một thông tin nền chút:

Tôi chỉ mới bắt đầu sử dụng Entity Framework 4.1 (EF) và Bộ luật đầu tiên để tạo ra các mô hình cho dự án ASP.NET MVC của tôi. Tôi cần một số mô hình tương tự như sau:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace TestApp.Models 
{ 
    public class Family 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 

     public virtual ICollection<Father> Fathers { get; set; } 
     public virtual ICollection<Mother> Mothers { get; set; } 
    } 

    public class Mother 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     public int FamilyID { get; set; } 

     public virtual ICollection<Child> Children { get; set; } 
     public virtual Family Family { get; set; } 
    } 

    public class Father 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     public int FamilyID { get; set; } 

     public virtual ICollection<Child> Children { get; set; } 
     public virtual Family Family { get; set; } 
    } 

    public class Child 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     public int MotherID { get; set; } 
     public int FatherID { get; set; } 

     public virtual Mother Mother { get; set; } 
     public virtual Father Father { get; set; } 
    } 
} 

Và DbContext:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Data.Entity; 

namespace TestApp.Models 
{ 
    public class TestContext : DbContext 
    { 
     public DbSet<Family> Families { get; set; } 
     public DbSet<Mother> Mothers { get; set; } 
     public DbSet<Father> Fathers { get; set; } 
     public DbSet<Child> Children { get; set; } 
    } 
} 

(Xin tha cho ví dụ khập khiễng, đó là những gì não chiên thứ sáu của tôi đã có thể đưa ra.)

Một gia đình có thể có nhiều bà mẹ và một số người cha. Và một đứa trẻ có một người mẹ và một người cha. Tôi đã kiểm tra với một trong những chuyên gia .NET tại nơi làm việc của tôi, người đã đồng ý rằng không có gì lạ thường trong việc này. Ít nhất là chúng ta có thể thấy.

Nhưng khi tôi chạy mã, tôi nhận được ngoại lệ này:

System.Data.SqlServerCe.SqlCeException: Mối quan hệ tham chiếu sẽ cho kết quả trong một tài liệu tham khảo có tính chu kỳ mà không được phép. [Constraint name = Mother_Family]

Tôi thấy chu kỳ: Family - Mother - Child - Father - Family. Nhưng nếu tôi tạo ra các bảng cơ sở dữ liệu bản thân mình (mà tôi không thích, đó là những gì tôi thích về Code First) nó sẽ là một cấu trúc dữ liệu hoàn toàn hợp lệ, theo như tôi có thể nói.

Vì vậy, câu hỏi đầu tiên của tôi là: Tại sao đây lại là vấn đề khi sử dụng mã trước? Có cách nào để nói với EF làm thế nào để xử lý đúng chu kỳ?

Sau đó, khi tôi viết ban đầu, trong khi tạo một dự án đơn giản để minh họa cho vấn đề của tôi, tôi tình cờ gặp phải một giải pháp khả thi. Tôi chỉ đơn giản là quên một số thuộc tính khi xác định các mô hình của tôi. Để rõ ràng trong ví dụ sau, thay vì loại bỏ chúng, tôi đã nhận xét ra các bộ phận của mô hình tôi quên:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace TestApp.Models 
{ 
    public class Family 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 

     public virtual ICollection<Father> Fathers { get; set; } 
     public virtual ICollection<Mother> Mothers { get; set; } 
    } 

    public class Mother 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     // public int FamilyID { get; set; } 

     public virtual ICollection<Child> Children { get; set; } 
     public virtual Family Family { get; set; } 
    } 

    public class Father 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     // public int FamilyID { get; set; } 

     public virtual ICollection<Child> Children { get; set; } 
     public virtual Family Family { get; set; } 
    } 

    public class Child 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     // public int MotherID { get; set; } 
     // public int FatherID { get; set; } 

     public virtual Mother Mother { get; set; } 
     public virtual Father Father { get; set; } 
    } 
} 

Vì vậy, loại bỏ những SomethingID tính tham khảo dường như để giải quyết vấn đề của tôi. Như bạn có thể thấy trong bộ điều khiển của dự án mẫu tôi đang liên kết đến ở cuối bài đăng này, tôi vẫn có thể xoay vòng tất cả các cách xung quanh và thực hiện các công cụ như mothers.First().Family.Fathers.First().Children.First().Mother.Family.Name mà không gặp bất kỳ sự cố nào. Nhưng tất cả các hướng dẫn và ví dụ về mô hình EF và Code First tôi đã xem (ví dụ: this one by Scott Guthrie) bao gồm các thuộc tính này, do đó, cảm thấy sai khi không sử dụng chúng.

Và vì vậy, câu hỏi thứ hai của tôi là: Sẽ có bất kỳ hạn chế và vấn đề nào mà tôi chưa phát hiện được không?

Tải xuống dự án mẫu tại đây: http://blackfin.cannedtuna.org/cyclical-reference-test-app.zip và mở TestSolution.sln. Các thuộc tính được nhận xét trong dự án ví dụ. Bỏ ghi chú dòng trong TestModels.cs để thêm các thuộc tính, dẫn đến ngoại lệ tham chiếu chu kỳ.

NB: Giải pháp là tạo và tạo một cơ sở dữ liệu SQL CE có tại c: \ TestApp.sdf

Cập nhật, tháng 12 năm 2011: Tôi chưa bao giờ giải quyết vấn đề này về mặt kỹ thuật, nhưng tôi bỏ công việc của mình và tìm một công việc khác mà tôi không phải sử dụng công nghệ của Microsoft. Đó là loại được giải quyết vấn đề của tôi :)

Là nơi hỗ trợ kỹ thuật tại địa điểm cũ được sử dụng để viết khi khắc phục sự cố: "Giải pháp hoặc giải pháp đã được cung cấp".

+0

Một trong những câu hỏi hay hơn tôi đã đọc trên SF. Làm tốt. Rất vui khi bạn nhận được 'giải pháp' của bạn! –

Trả lời

0

Đây là vấn đề đã biết và bạn không phải là người đầu tiên gặp phải sự cố. Từ những gì tôi nghe nói họ đang làm việc trên một giải pháp tốt hơn trong phiên bản WCF sắp tới, tuy nhiên trong thời gian từ kinh nghiệm của tôi, bạn nên tạo DataContracts đại diện cho dữ liệu được gửi qua dây. để loại bỏ tham chiếu tuần hoàn.

Tôi biết đó là một nỗi đau, nhưng có nhiều lợi ích khác mà bạn có thể muốn thực hiện các thay đổi khác đối với cấu trúc mà khách hàng của bạn sử dụng thay vì cho phép họ chơi với các đối tượng khi chúng tồn tại trong db của bạn

+0

Nhưng không phải là DataContracts được sử dụng để mô tả dữ liệu cho tuần tự hóa? Tôi thậm chí không ở serialization được nêu ra. – decibyte

3

Nhưng nếu tôi tạo ra các bảng cơ sở dữ liệu bản thân mình (mà tôi không muốn, đó là những gì tôi thích về luật đầu tiên) nó sẽ là một cấu trúc dữ liệu hoàn toàn hợp lệ, như xa như tôi có thể nói.

Đây là điều bạn nên kiểm tra kỹ. Ngoại lệ xuất phát trực tiếp từ cơ sở dữ liệu chứ không phải từ Entity Framework. Nó có khả năng cũng là một cấu trúc bảng với các ràng buộc giống nhau được tạo ra bằng tay sẽ không hợp lệ. Xin lưu ý rằng các thuộc tính khóa ngoài của bạn Mother.FamilyID, Father.FamilyID, Child.MotherIDChild.FatherIDkhông được rỗng, vì vậy chúng đại diện cho các mối quan hệ bắt buộc và các cột tương ứng trong cơ sở dữ liệu cũng không thể rỗng.

Khi bạn xóa tất cả các thuộc tính này khỏi lớp mô hình của mình, mối quan hệ của bạn đột nhiên trở thành tùy chọn vì thuộc tính điều hướng có thể là null. Đây là một mô hình khác vì các cột FK trong DB có thể được vô hiệu hóa! Rõ ràng đây là một mô hình cho phép.

Nếu bạn muốn có tính chất then chốt vẫn ngoại trong mô hình của bạn mà đại diện tùy chọn thay vì mối quan hệ cần thiết bạn có thể sử dụng các loại nullable: public int? FamilyID { get; set; }, public int? MotherID { get; set; } vv

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