2009-03-13 33 views
22

Bất cứ khi nào tôi tải một lớp Task, thuộc tính Document luôn luôn rỗng, mặc dù có dữ liệu trong db.fluent nhibernate HasOne WithForeignKey không hoạt động

nhiệm lớp:

public class Task 
{ 
    public virtual Document Document { get; set; } 

công tác lập bản đồ ghi đè cho AutoPersistenceModel:

public void Override(AutoMap<Task> mapping) 
{ 
    mapping.HasOne(x => x.Document) 
     .WithForeignKey("Task_Id"); 

Như bạn có thể nhìn thấy hình gì NHProf nói là được chạy, điều kiện tham gia là sai, doesnt WithForeignKey dường như có hiệu lực. Trong thực tế, tôi có thể viết bất kỳ chuỗi trong mã trên và nó làm cho không có sự khác biệt.

FROM [Task] this_ 
    left outer join [Document] document2_ 
    on this_.Id = document2_.Id 

Nó nên là:

FROM [Task] this_ 
    left outer join [Document] document2_ 
    on this_.Id = document2_.Task_Id 

Nếu tôi hack dữ liệu trong db để id phù hợp, sau đó dữ liệu được nạp, nhưng rõ ràng đây là không chính xác - nhưng ít nhất nó chứng tỏ nó tải dữ liệu.

Edit: lục lọi trong nguồn NHib thạo để tìm ra XML sản xuất này:

<one-to-one foreign-key="Task_Id" cascade="all" name="Document" class="MyProject.Document, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 

Edit: heres schema:

CREATE TABLE [dbo].[Document](
[Id] [int] IDENTITY(1,1) NOT NULL, 
[Task_Id] [int] NOT NULL, 

CREATE TABLE [dbo].[Task](
[Id] [int] IDENTITY(1,1) NOT NULL, 

Bất cứ ai có ý tưởng nào?

Cảm ơn

Andrew

Trả lời

5

Tôi nghĩ vấn đề ở đây là "HasOne" ước có nghĩa là bạn đang chỉ tay vào điều khác (cách tiêu chuẩn quan hệ để nói "Nhiều Để One"/"Một đến một"); Bằng cách đặt một Task_ID trên tài liệu, mối quan hệ thực sự là HasMany nhưng bạn có một số hiểu biết ngầm định rằng sẽ chỉ có một tài liệu cho mỗi tác vụ.

Xin lỗi - Tôi không biết cách khắc phục điều này, nhưng tôi sẽ quan tâm xem giải pháp là gì (Tôi không sử dụng NHibernate hoặc Fluent NHibernate, nhưng tôi đã nghiên cứu để sử dụng trong tương lai) . Một giải pháp (từ một ai đó có ý tưởng rất ít) sẽ làm cho Documents trở thành một bộ sưu tập trên Task, và sau đó cung cấp một thuộc tính Document trả về bộ sưu tập đầu tiên trong bộ sưu tập (sử dụng giao diện ẩn thuộc tính Documents để không ai nghĩ rằng họ có thể thêm mặt hàng mới cho nó).

Nhìn qua tài liệu và xem xét câu trả lời eulerfx của, Có lẽ phương pháp này sẽ là một cái gì đó như:

References(x => x.Document) 
    .TheColumnNameIs("ID") 
    .PropertyRef(d => d.Task_ID); 

EDIT: Chỉ cần để câu trả lời này có giải pháp thích hợp: Con đường đúng là để cập nhật database schema để phù hợp với ý định của mã. Điều đó có nghĩa là thêm một DocumentID vào bảng Task, do đó, có một mối quan hệ Nhiều-To-One giữa Task và Document. Nếu không thể thay đổi giản đồ, Tham chiếu() sẽ là độ phân giải thích hợp.

+0

Một khả năng tôi đồng ý, nhưng tại sao Task_Id không được hiển thị ở bất kỳ đâu? (ngay cả khi nó sai và do đó sẽ gây ra một ngoại lệ - nhưng nó không) –

+0

Điều đó không làm việc, tuy nhiên nó có nghĩa là tôi cần một tài sản Task_id trên tài liệu, mà tôi không muốn có. Hoạt động bây giờ mặc dù cảm ơn –

6

Bạn nên sử dụng:

Tham chiếu (x => x.Tài liệu, "DocumentIdColumnOnTask")

+0

tblDocument có Task_Id, không tblTask ​​có Document_Id –

+0

Oh ok bỏ lỡ phần đó. Sau đó, tôi cho rằng nó sẽ có ý nghĩa nhất để có một docID trên bảng nhiệm vụ. Nếu không cấu trúc bảng chỉ ra rằng có thể có các tài liệu khác nhau cho một tác vụ. – eulerfx

+0

Vâng tôi cho là vậy. Có một lý do giống như nó là nhưng tôi không thể nhớ tại sao. Ill có một suy nghĩ và xem xét đảo ngược nó. ta –

0

Như eulerfx chỉ ra,

cấu trúc bảng chỉ ra rằng có lẽ mulitple tài liệu cho một nhiệm vụ

và Chris nói:

Bằng đặt một Task_ID trên tài liệu, mối quan hệ thực sự là HasMany nhưng bạn có một số hiểu biết ngầm định rằng sẽ chỉ có một tài liệu cho mỗi tác vụ.

Đây là khóa học hoàn toàn chính xác vì vậy tôi đã đảo ngược nó để Tác vụ có Document_Id không có giá trị.

Nhờ cả hai bạn giúp đỡ bạn!

Tôi lật một xu cho câu trả lời được chấp nhận, nếu tôi có thể đánh dấu cả hai tôi sẽ!

+0

hey andrew, PLN đang giải mã câu trả lời. Tôi sẽ nói rằng bằng cách làm lại db bạn đã thực sự làm điều đúng. Nhưng đôi khi bạn không thể thay đổi DB, và đây là nơi các Ánh xạ Fluent thực sự tỏa sáng. HasOne là một tính năng như vậy, và cả bạn và tôi đều sử dụng nó một cách không chính xác. PLN chỉ đúng cách để sử dụng nó ... 2 xu của tôi – andy

91

Tôi đã gặp sự cố tương tự ngay hôm nay. Tôi tin rằng các trick không được sử dụng .ForeignKey (...) với ánh xạ .HasOne, nhưng để sử dụng .PropertyRef (...) thay thế. Sau đây là cách tôi xác định một mối quan hệ One-to-one giữa một tổ chức (mẹ) và quản lý của mình (trẻ em):

HasOne(x => x.Admin).PropertyRef(r => r.Organisation).Cascade.All(); 

các Admin có một tài liệu tham khảo đơn giản để tổ chức sử dụng ngoại của nó chính:

References(x => x.Organisation, "ORAD_FK_ORGANISATION").Not.Nullable(); 

Khi truy xuất Tổ chức, thao tác này sẽ tải lên bản ghi Quản trị viên chính xác và sắp xếp đúng các cập nhật và xóa.

+0

Có vẻ như câu trả lời hoàn hảo sẽ là sự kết hợp của điều này và câu trả lời của Chris Shaffer. Câu trả lời này cung cấp một implimentation làm việc bằng cách sử dụng Fluent NHibernate và Chris Shaffer cung cấp một chút về 'lý thuyết' về lý do tại sao việc thực hiện ban đầu không hoạt động. –

+0

Cảm ơn ... đã làm việc cho tôi – dbones

+0

cũng đã làm việc cho tôi, cảm ơn bạn rất nhiều. Nhưng HasOne(). ForeignKey() là gì? – whitestream

0

tôi đã phải vật lộn với cùng Có Một vấn đề và cuối cùng phát hiện ra rằng làm việc này:

public class ParentMap : ClassMap<Parent> 
{ 
    public ParentMap() 
    { 
     Id(x => x.Id); 
     HasOne(s => s.Child).Cascade.All(); 
    } 
} 

public class ChildMap : ClassMap<Model.Child> 
{ 
    public ChildMap() 
    { 
     Id(x => x.Id); 
     HasOne(s => s.Parent).Constrained().ForeignKey();   
    } 
} 
+0

làm thế nào để làm với compositeid trong cả hai bảng? – DanielVorph

2

Tôi đã thử giải pháp này:

chỉ tại văn bản:

mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All(); 
Các vấn đề liên quan