FreeSql 支持導航屬性延時加載,即當我們需要用到的時候才進行加載(讀取),支持1對1、多對1、1對多、多對多關系的導航屬性。
當我們希望瀏覽某條訂單信息的時候,才顯示其對應的訂單詳細記錄時,我們希望使用延遲加載來實現,這樣不僅加快的了 讀取的效率,同時也避免加載不需要的數據。延遲加載通常用于foreach循環讀取數據時。
那么我們在定義Model的時候,需要在屬性前面添加virtual關鍵字。如下
public class Order {[Column(IsPrimary = true)]public int OrderID { get; set; }public string OrderTitle { get; set; }public string CustomerName { get; set; }public DateTime TransactionDate { get; set; }public virtual List<OrderDetail> OrderDetails { get; set; }
}
public class OrderDetail {[Column(IsPrimary = true)]public int DetailId { get; set; }public int OrderId { get; set; }public virtual Order Order { get; set; }
}
延時加載功能默認被關閉的,使用此功能請時,請在申明處開啟;
延時加載功能,依賴 FreeSql.Extensions.LazyLoading 包,請前往 nuget 下載;
IFreeSql fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10").UseLazyLoading(true) //開啟延時加載功能.UseMonitorCommand(cmd => Console.WriteLine(cmd.CommandText)) //監聽SQL命令對象,在執行前.Build();var order = fsql.Select<Order>().Where(a => a.OrderID == 1).ToOne(); //查詢訂單表
var orderDetail1 = order.OrderDetails; //第一次訪問,查詢數據庫
var orderDetail2 = order.OrderDetails; //第二次訪問,不查
var order1 = orderDetail1.FirstOrDefault(); //訪問導航屬性,此時不查數據庫,因為 OrderDetails 查詢出來的時候已填充了該屬性
控制臺輸出內容:
SELECT a.`OrderID`, a.`OrderTitle`, a.`CustomerName`, a.`TransactionDate`
FROM `Order` a
WHERE (a.`OrderID` = 1)
limit 0,1SELECT a.`DetailId`, a.`OrderId`
FROM `OrderDetail` a
WHERE (a.`OrderId` = 1)
FreeSql延時加載支持1對1、多對1、1對多、多對多關系的導航屬性,前三者大小同異,以下我們單獨介紹多對多關系。
多對多延時加載
public partial class Song {[Column(IsIdentity = true)]public int Id { get; set; }public DateTime? Create_time { get; set; }public bool? Is_deleted { get; set; }public string Title { get; set; }public string Url { get; set; }public virtual ICollection<Tag> Tags { get; set; }
}
public partial class Song_tag {public int Song_id { get; set; }public virtual Song Song { get; set; }public int Tag_id { get; set; }public virtual Tag Tag { get; set; }
}
public partial class Tag {[Column(IsIdentity = true)]public int Id { get; set; }public int? Parent_id { get; set; }public virtual Tag Parent { get; set; }public decimal? Ddd { get; set; }public string Name { get; set; }public virtual ICollection<Song> Songs { get; set; }
}
如上有三個表,音樂、標簽,以及他們的關系表。
var songs = fsql.Select<Song>().Limit(10).ToList(); //取10條音樂
var songs1 = songs.First().Tags; //第一次訪問,查詢數據庫
var songs2 = Songs.First().Tags; //第二次訪問,不查
控制臺輸出內容:
SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url`
FROM `Song` a
limit 0,10SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name`
FROM `Tag` a
WHERE (exists(SELECT 1
FROM `Song_tag` b
WHERE (b.`Song_id` = 2 AND b.`Tag_id` = a.`Id`)
limit 0,1))
總結
優點:只在需要的時候加載數據,不需要預先計劃,避免了各種復雜的外連接、索引、視圖操作帶來的低效率問題。
缺陷:多次與DB交互,性能降低。
如果要在循環中使用數據,請使用貪婪加載,否則使用懶加載。
系列文章導航
(一)入門
(二)自動遷移實體
(三)實體特性
(四)實體特性 Fluent Api
(五)插入數據
(六)批量插入數據
(七)插入數據時忽略列
(八)插入數據時指定列
(九)刪除數據
(十)更新數據
(十一)更新數據 Where
(十二)更新數據時指定列
(十三)更新數據時忽略列
(十四)批量更新數據
(十五)查詢數據
(十六)分頁查詢
(十七)聯表查詢
(十八)導航屬性
(十九)多表查詢
(二十)多表查詢 WhereCascade
(二十一)查詢返回數據
(二十二)Dto 映射查詢
(二十三)分組、聚合
(二十四)Linq To Sql 語法使用介紹
(二十五)延時加載
(二十六)貪婪加載 Include、IncludeMany、Dto、ToList
(二十七)將已寫好的 SQL 語句,與實體類映射進行二次查詢
(二十八)事務
(二十九)Lambda 表達式
(三十)讀寫分離
(三十一)分區分表
(三十二)Aop
(三十三)CodeFirst 類型映射
(三十四)CodeFirst 遷移說明
(三十五)CodeFirst 自定義特性