2009-03-01 46 views
0

我剛開始學習LINQ2SQL,我想嘗試的第一件事情是簡單的父子層次結構,但似乎找不到一個好辦法。我在這裏看到了一些例子,並且我已經使用了Google,但是我不能直接應用它們,所以我會解釋我想要完成的工作。與LINQ2SQL和POCO對象的親子關係

讓我們使用帶有標籤的常見示例。

數據庫表:Post-- Post_Tags - 標籤

我創建了一個簡單的郵政類,所以我儘量避免周圍路過LINQ2SQL類:

public class Post 
{ 
    public int Id {get; set;} 
    public int Title {get; set;} 
    public IEnumerable<string> Tags {get; set;} 
} 

我想選擇5個最新記錄Posts表格,獲取他們的相關標籤並返回IList,其中每個Post都有其標籤屬性填充。

你能告訴我一個具體的Linq2Sql代碼我該怎麼做?

我想:

 IList<Post> GetLatest() 
     { 
      return (from p in _db.Posts 
        orderby p.DateCreated descending 
        select new Post 
        { 
         Id = p.Id, 
         Title = p.Title, 
         Tags = p.Post_Tags.Select(pt => pt.Tag.Name) 
        }).Take(5).ToList(); 
     } 

這工作,但複製發表記錄每個標籤記錄,我在每一個方法,我的用戶複製屬性映射(ID = p.Id,...)。然後,我嘗試這種方法,但在這種情況下,我有一個往返到數據庫爲每個變量:

 IQueryable<Post> GetList() 
     { 
      return (from p in _db.Posts 
        select new Post 
        { 
         Id = p.Id, 
         Title = p.Title, 
         Tags = p.Post_Tags.Select(pt => pt.Tag.Name) 
        }); 
     } 

     IList<Post> GetLatest() 
     { 
      return (from p in GetList() 
        orderby p.DateCreated descending 
        select p).Take(5).ToList(); 
     } 

如果我是在經典的ADO.NET這樣做,我會創建一個存儲過程返回兩個結果。一個帶有Post記錄,另一個帶有相關的Tag記錄。然後,我會將它們映射到代碼中(由DataRelation,ORM等人手)。我可以使用LINQ2SQL嗎?

我真的好奇看到一些代碼示例你們如何處理這樣簡單的層次結構。

是的,我真的很想返回IList <>對象和我的自定義類,而不是可查詢的Linq to Sql對象,因爲我想靈活地瞭解數據訪問代碼,例如,如果我決定放棄Linq2Sql。

謝謝。

回答

1

如果您創建一個DataContext,則會爲您自動維護父子關係。

即如果建模郵電標籤和他們的一個LINQ2SQL DataContext的內部關係,您就可以獲取帖子是這樣的:

var allPosts = from p in _db.Posts 
       orderby p.DateCreated descending 
       select p; 

然後,你將不必擔心在所有的任何標記,因爲他們是作爲變量p的成員訪問爲:

var allPostsList = allPosts.ToList(); 

var someTags = allPostsList[0].Post_Tags; 
var moreTags = allPostsList[1].Post_Tags; 

然後重複任何實例,然後自動在整個的DataContext,直到你問它的SubmitChanges()更新;

IMO,這是ORM的要點,您不需要重新創建模型類並在許多地方維護映射,因爲您希望ORM爲您管理所有這些關係。

至於往返,如果從明確請求訪問數據庫的任何代碼避免,所有查詢都將被存儲在一箇中間查詢表示,只有實際需要的數據繼續,是當該查詢將被轉換爲sql並分派到數據庫以獲取結果。

即下面的代碼只能訪問數據庫一次

// these 3 variables are all in query form until otherwise needed 
var allPosts = Posts.All(); 
var somePosts = allPosts.Where(p => p.Name.Contains("hello")); 
var lesserPosts = somePosts.Where(p => p.Name.Contains("World")); 

// calling "ToList" will force the query to be sent to the db 
var result = lesserPosts.ToList(); 
+0

謝謝您的回答,但最重要的,這是我不希望靠LINQ2SQL課後的DAL。 – muerte 2009-03-01 16:08:10

0

怎麼樣,如果你的職位設置你的DataLoadOptions先明確加載標籤?喜歡的東西:

IList<Post> GetLatest() 
{ 
    DataLoadOptions options = new DataLoadOptions(); 
    options.LoadWith<Post>(post => post.Tags); 
    _db.LoadOptions = options; 

    return (from p in _db.Posts 
      orderby p.DateCreated descending) 
      Take(5).ToList(); 
    } 
+0

我試了一下,它仍然n次到數據庫。我不能做post => post.Tags,但post => post.Post_Tags – muerte 2009-03-01 16:43:31

0
List<Post> latestPosts = db.Posts 
    .OrderByDescending(p => p.DateCreated) 
    .Take(5) 
    .ToList(); 

    // project the Posts to a List of IDs to send back in 
List<int> postIDs = latestPosts 
    .Select(p => p.Id) 
    .ToList(); 

// fetch the strings and the ints used to connect 
ILookup<int, string> tagNameLookup = db.Posts 
    .Where(p => postIDs.Contains(p.Id)) 
    .SelectMany(p => p.Post_Tags) 
    .Select(pt => new {PostID = pt.PostID, TagName = pt.Tag.Name }) 
    .ToLookup(x => x.PostID, x => x.TagName); 
//now form results 
List<Post> results = latestPosts 
    .Select(p => new Post() 
    { 
    Id = p.Id, 
    Title = p.Title, 
    Tags = tagNameLookup[p.Id] 
    }) 
    .ToList(); 
+0

因此,這將做2次往返數據庫? – 2009-06-04 01:49:52