FreeSql (二十五)延時加載


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 下載;

static 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(); //請務必定義成 Singleton 單例模式

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,1

SELECT 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,10

SELECT 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交互,性能降低。

如果要在循環中使用數據,請使用貪婪加載,否則使用懶加載。

系列文章導航


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM