物件關聯對應中,資料表間必然存在關聯。LINQ to SQL 支援兩種聯結方式:
where 子句進行查找join 子句以 Blog 與 Post 為例,查詢特定文章及其所屬部落格。先定義 Blog 對應:
[Table(Name="blogs")]
public class Blog {
[Column(Name="blogid", IsPrimaryKey=true, IsDbGenerated=true)] public int Id { get; set; }
[Column] public int UserId { get; set; }
[Column] public string Name { get; set; }
[Column] public DateTime CreateDate { get; set; }
public IList<Post> Posts { get; set; } // 暫不建立對應
}
var result = from blog in blogs
from post in posts
where post.BlogId == blog.Id && post.Id == 2
select new { BlogName = blog.Name, PostTitle = post.Title, PostBody = post.Body };
產生 SQL 使用舊式 ANSI-82 聯結語法。
var result = from blog in blogs
join post in posts on blog.Id equals post.BlogId
where post.Id == 2
select new { BlogName = blog.Name, PostTitle = post.Title, PostBody = post.Body };
產生標準 INNER JOIN SQL。注意:LINQ to SQL 的 on 子句左右順序必須與查詢來源順序對應(outer key selector / inner key selector),否則編譯錯誤。
使用 DefaultIfEmpty() 擴充方法:
var result = from post in posts
join blog in blogs on post.BlogId equals blog.Id into joinblogs
from joinblog in joinblogs.DefaultIfEmpty()
where post.Id == 2
select new { BlogName = joinblog.Name, PostTitle = post.Title, PostBody = post.Body };
產生 LEFT OUTER JOIN SQL。
一般 ORM 框架透過物件關聯自動導航,LINQ to SQL 同樣支援。修改 Blog 對應:
[Association(OtherKey="BlogId")]
public EntitySet<Post> Posts { get; set; }
注意:需使用 EntitySet<T> 取代 IList<T>。查詢 Blog 時,關聯的 Post 自動載入:
var result = from blog in dbContext.GetTable<Blog>()
where blog.Id == 1
select blog;
foreach (var blog in result) {
Console.WriteLine(blog.Name);
foreach (var post in blog.Posts) Console.WriteLine(post.Title);
}
在 Post 類別中加入:
private EntityRef<Blog> _blog;
[Association(Storage="_blog", ThisKey="BlogId")]
public Blog Blog {
get { return _blog.Entity; }
set { _blog.Entity = value; }
}
使用 EntityRef<T> 支援延遲載入。查詢 Post 時自動載入所屬 Blog。
LINQ to SQL 預設不直接支援多對多,但社群有通用解決方案:MSDN 部落格範例。
雙邊皆使用 EntitySet 並設定 IsUnique=true。範例:User 與 Blog 一對一。
[Association(ThisKey="BlogId", OtherKey="Id", IsUnique=true)]
public EntitySet<Blog> Blog { get; set; }
Blog 端對應:
[Association(ThisKey="UserId", OtherKey="Id", IsUnique=true)]
public EntitySet<User> User { get; set; }
讀者反應篇幅過長,本篇專注關聯主題。系列目標將 LINQ 由淺入深完整講解,每篇為系列一個元組。