2009-08-21 51 views
6

我有2個相關的Linq to SQL問題。請參閱下面的圖片以查看我的模型的外觀。在自引用表中急切地加載Linq到SQL實體

問題1

我試圖找出如何渴望負載我User類/表中的User.AddedByUser領域。該字段是根據User.AddedByUserId字段中的關係生成的。該表是自引用的,我試圖找出如何讓Linq to SQL加載User.AddedByUser屬性,即任何User實體被加載/獲取時,它還必須獲取User.AddedByUser和User.ChangedByUser 。不過,據我所知,這可能成爲一個遞歸問題...

更新1.1:

我試圖使用DataLoadOptions如下:

var options = new DataLoadOptions(); 
options.LoadWith<User>(u => u.ChangedByUser); 
options.LoadWith<User>(u => u.AddedByUser); 

db = new ModelDataContext(connectionString); 
db.LoadOptions = options; 

但這並不工作,我得到以下例外的第2行:

System.InvalidOperationException occurred 
    Message="Cycles not allowed in LoadOptions LoadWith type graph." 
    Source="System.Data.Linq" 
    StackTrace: 
     at System.Data.Linq.DataLoadOptions.ValidateTypeGraphAcyclic() 
     at System.Data.Linq.DataLoadOptions.Preload(MemberInfo association) 
     at System.Data.Linq.DataLoadOptions.LoadWith[T](Expression`1 expression) 
     at i3t.KpCosting.Service.Library.Repositories.UserRepository..ctor(String connectionString) in C:\Development\KP Costing\Trunk\Code\i3t.KpCosting.Service.Library\Repositories\UserRepository.cs:line 15 
    InnerException: 

該例外是相當不言自明 - 對象圖不允許爲循環。 另外,假設第2行沒有拋出異常,我很確定第3行會,因爲它們是重複的鍵。

更新1.2

下列不工作,要麼(在一起選擇不使用更新1.1以上):

var query = from u in db.Users 
      select new User() 
      { 
       Id = u.Id, 
       // other fields removed for brevityy 
       AddedByUser = u.AddedByUser, 
       ChangedByUser = u.ChangedByUser, 

      }; 
return query.ToList(); 

它引發以下,不言自明的例外:

System.NotSupportedException occurred 
Message="Explicit construction of entity type 'i3t.KpCosting.Shared.Model.User' in query is not allowed." 

我現在真的很在意如何解決這個問題。請幫忙!

問題2

在我的DB所有其他表,因此LINQ到SQL模式,我有兩個字段,Entity.ChangedByUser(與Entity.ChangedByUserId外鍵/關係)和Entity.AddedByUser(與Entity.AddedByUserId外鍵/ relationship)

如何讓Linq to SQL真正爲我加載這些字段?我是否需要對我的查詢做一個簡單的連接?或者是否有其他方法?

Linq to SQL eager loading on self referencing table http://img245.imageshack.us/img245/5631/linqtosql.jpg

回答

3

也許你可以嘗試退後一步,看到你想要什麼與關係?我假設你想要將這些信息顯示給用戶。 「Iain Galloway 8小時前修改」。

可以像下面的工作? : -

var users = from u in db.Users 
      select new 
      { 
       /* other stuff... */ 
       AddedTimestamp = u.AddedTimestamp, 
       AddedDescription = u.AddedByUser.FullName, 
       ChangedTimestamp = u.ChangedTimestamp, 
       ChangedDescription = u.ChangedByUser.FullName 
      }; 

我已經使用匿名類型(imo)清晰。如果您願意,您可以將這些屬性添加到您的用戶類型。

至於你的第二個問題,你正常的LoadWith(x => x.AddedByUser)等應該工作得很好 - 雖然我傾向於更喜歡直接在數據庫中存儲描述字符串 - 你有一個權衡在你的描述更新時,當ChangedByUser.FullName發生變化時,如果ChangedByUser被刪除(例如ON DELETE CASCADE,或者在你的代碼中處理一個空的ChangedByUser),必須做一些複雜的操作並且可能違反直覺。

+0

是的我想在我的GUI中顯示該信息。我希望能夠在不使用匿名類型的情況下解決這個問題。但我想這是解決問題的一種方式。我的問題與Linq to SQL無法應對多對多關係有關嗎? – 2009-09-08 14:27:32

+0

Na,您可以將User.AddedDescription和User.ChangedDescription字段添加到User類,然後您不必使用anon類型。 這與許多關係(你的例子中的每個關係都是1:1)沒有任何關係。 如果你直接編寫你的SQL,你不想獲得AddedByUser的所有屬性(包括他的AddedByUser等等無窮大)。你可能會抓住他的名字和/或你需要的任何細節。 伊莫這是一個更普遍的O/RM問題。我想你會遇到與L2E或Hibernate相同的問題。 – 2009-09-09 10:56:41

0

不知道有這個問題的LINQ到SQL的解決方案。如果您使用的是Sql Server 2005,則可以定義一個(類似遞歸的)Stored Procecdure,它使用公用表表達式來獲得所需的結果,然後使用DataContext.ExecuteQuery執行該結果。

4

Any type of cycles just aren't allowed。由於LoadWith<T>AssociateWith<T>適用於上下文中的每種類型,因此沒有防止無限循環的內部方法。更準確地說,它只是混淆瞭如何創建SQL,因爲SQL Server沒有CONNECT BYCTEs真的超過了Linq可以使用提供的框架自動生成的內容。

您可以使用的最佳選擇是手動將1級聯接下拉到用戶表和子匿名類型以返回它們。對不起,這不是一個乾淨/簡單的解決方案,但它到目前爲止與Linq完全一樣。