在本文中,我們將介紹如何使用DAPPER從單個資料庫調用中讀取資料庫中的多個結果集。我們將看看我們可能希望這樣做的場景,以及如何使用它的Query和QueryMultiple方法更簡潔地實現這一點。 當我們談論以數據為中心的應用程式時,可能會出現一些場景,在這些場景中我們可能希望從資料庫中檢索多重結 ...
在本文中,我們將介紹如何使用DAPPER從單個資料庫調用中讀取資料庫中的多個結果集。我們將看看我們可能希望這樣做的場景,以及如何使用它的Query和QueryMultiple方法更簡潔地實現這一點。 當我們談論以數據為中心的應用程式時,可能會出現一些場景,在這些場景中我們可能希望從資料庫中檢索多重結果。多個結果集既可以是相關的,也可以是無關的。要做到這一點,我們不需要對資料庫進行多次往返,而是可以在一次資料庫調用本身中實際使用dapper檢索結果,然後將結果映射到代碼中的所需對象。 在我們繼續並開始研究如何做到這一點之前,讓我們首先試著理解在我們的應用程式中可能希望做到這一點的場景: 1、查詢無關實體:所請求的實體根本不相關。 2、查詢具有1至多個關係的相關實體:被請求的實體具有1對多的關係,我們需要在代碼中處理多個結果集 3、查詢具有1至1關係的相關實體:被請求的實體具有1-1關係,我們需要在代碼中執行處理多個映射 在第一個場景中,我們有完全不相關的實體,因此基本上,我們只想執行兩個獨立的查詢來檢索數據,然後將其映射到這些實體。在第二個場景中,返回的實體與1-多相關,因此我們希望檢索數據,然後將結果映射到具有1至多個關係的POCO中。最後,在第三個場景中,返回的實體是1-1,因此我們希望檢索數據,然後將結果映射到具有1-1關係的POCO中。 現在讓我們看看一些代碼,瞭解如何使用Dapper來實現這一切。 所有這些都可以通過DAPPER的查詢、QueryMultiple和Read方法進行歸檔。現在讓我們把重點放在如何在代碼中執行這些操作。
查詢無關實體
假設我們想從API中檢索書籍和視頻列表。我們可以通過兩個簡單的選擇所有查詢來實現這一點,資料庫結果看起來如下:
現在,為了能夠從代碼中執行同樣的操作,我們首先需要定義我們的實體:
1 public class Book 2 { 3 public int ID { get; set; } 4 public string BookName { get; set;} 5 public string ISBN { get; set; } 6 } 7 8 public class Video 9 { 10 public int ID { get; set; } 11 public string VideoName { get; set; } 12 }
使用這些模型,讓我們看看如何只使用一個資料庫調用來使用DAPPER檢索這些結果:
1 public IActionResult Index() 2 { 3 // define our SQL query - it contains mulitple queries seprated by ; 4 var query = "SELECT * from Books; Select * from Videos"; 5 6 // Execute the query 7 var results = dbConnection.QueryMultiple(query); 8 9 // retrieve the results into the respective models 10 var books = results.Read<Book>(); 11 var videos = results.Read<Video>(); 12 13 return Ok(new { Books = books, Videos = videos}); 14 }
現在讓我們在POSTMAN中運行,以查看行動中的結果:
註意:我已經創建了一個簡單的API控制器來測試這個代碼,所有的DB訪問代碼都在裡面運行。這隻是為了演示目的和現實世界的應用,這樣的代碼根本不應該被使用。
查詢具有1到多關係的查詢相關實體
檢索相關實體的另一個典型場景是實體之間存在一對多關係。讓我們嘗試使用組織和聯繫人的例子來可視化這一點。組織通常具有與其關聯的多個聯繫人。如果我們想要檢索一個組織,並且想要檢索所有關聯的聯繫人,我們可以利用QueryMultiple來做到這一點。這就是關係在資料庫中的樣子。
首先讓我們檢查一下如何使用SQL查詢做同樣的操作。
現在,如果我們必須在代碼中做同樣的事情,我們首先需要定義我們的實體。請註意,我們的實體也將建模一對多關係的方式,每個組織有一個聯繫人列表。
public class Organization { public int ID { get; set; } public string OrganizationName { get; set; } public List<contact> Contacts { get; set; } } public class Contact { public int ID { get; set; } public int OrganizationId { get; set; } public string ContactName { get; set; } } </contact>
現在讓我們看一下用於檢索這些相關實體的代碼,並瞭解如何用dapper的QueryMultiple方法填充與1到多個關係相關的實體。
[HttpGet("{id}")] public IActionResult GetOrganization(int id) { // define our SQL query - it contains mulitple queries seprated by ; var query = @"SELECT* from Organizations where id = @id; Select * from Contacts where OrganizationId = @id"; // Execute the query var results = dbConnection.QueryMultiple(query, new { @id = id }); // retrieve the results into the respective models var org = results.ReadSingle<Organization>(); org.Contacts = results.Read<Contact>().ToList(); return Ok(org); }
在上面的代碼中,我們可以看到我們是如何同時執行2個查詢的。我們接受了第一個查詢結果並填充了我們的組織對象。第二個查詢結果作為同一個組織對象的聯繫人集合被推送。
現在讓我們在POSTMAN中運行,以查看行動中的結果:
具有1到1關係的查詢相關實體
前兩個場景非常簡單,因為它們要求我們編寫兩個獨立的查詢,然後獨立收集每個查詢的結果,以便根據需要創建模型對象。
但是有1到1個關係的場景是很棘手的。從資料庫的角度來看,我們可以在單個SQL查詢本身中檢索相關實體,但是隨後我們希望將單個結果集映射到代碼中的多個對象中。這可以使用在DAPPER中可用的多重映射特征來完成。讓我們在一個例子的幫助下理解這一點。
註意:我們仍然可以使用與1到許多關係相同的方法來檢索與1到1相關的數據,但是本節將展示如何使用單個SQL並映射結果。
讓我們舉一個聯繫和護照的例子。每個聯繫人只能有一個護照。讓我們先想象一下這個資料庫關係。
現在,讓我們看看是否需要從資料庫中檢索聯繫人列表及其護照信息,我們如何用SQL實現這一點。
現在讓我們看看我們的實體如何尋找聯繫和護照。
public class Contact { public int ID { get; set; } public int OrganizationId { get; set; } public string ContactName { get; set; } public Passport Passport { get; set; } } public class Passport { public int ID { get; set; } public int Contactid { get; set; } public string PassportNumber { get; set; } }
現在讓我們看看如何從資料庫中檢索這些相關實體,並使用更簡潔的多重映射完整地填充具有相同關係的POCOs。
[HttpGet("{id}")] public IActionResult GetContact(int id) { var query = @"Select c.ID, c.Organizationid, c.ContactName, p.ID as PassPortId, p.ContactId, p.PassportNumber from Contacts c, Passports p where c.ID = p.ContactID and c.id = @id"; // Execute the query var contact = dbConnection.Query<Contact, Passport, Contact>(query, MapResults, new { @id = id }, splitOn: "PassportId"); return Ok(contact); } private Contact MapResults(Contact contact, Passport passport) { contact.Passport = passport; return contact; }
在上面的代碼中,我們使用的是查詢方法的重載版本,它採用多個類型。傳遞的類型是我們要映射的每個對象的類型參數,最後一個類型參數是表示該查詢將返回的對象類型的附加參數。
因此,在我們的查詢中,我們希望將結果映射到類型Contact和Passsport,然後期望結果返回到類型Contact的對象中。
現在,讓我們看看在查詢方法中傳遞的實際參數。
第一個參數是SQL查詢本身。
第二個參數是映射函數,它將獲取結果,將它綁定到相應的類型,然後創建所需的返回類型並返回該返回類型。在我們的代碼中,它採用Contact和Passport類型,並將Contact的Passport屬性指定為正在傳遞的Passport值。一旦這樣做,結果接觸類型返回。
第三個參數是命令參數@ id。
最後一個參數拆分是將告訴DAPPER哪些列必須映射到下一個對象的列名。在我們的示例中,我們將此值作為PassportId傳遞,這意味著在找到PassportId列之前,所有列都將映射到第一種類型,即Contact,然後隨後的列將被映射到下一個參數類型,即Passport。
註意:如果我們有2個以上的對象需要映射,splitOn將是一個逗號分隔的列表,其中每個列名將充當分隔符,並開始下一個對象類型的映射列。
現在讓我們在POSTMAN中運行,以查看行動中的結果:
歐了,我們使用DAPPER從資料庫中檢索多個結果集,以避免資料庫往返。
總結:
在本文中,我們討論瞭如何使用dapper提供的特性在一次運行中檢索多個相關或無關的實體,從而避免多次資料庫往返。這是從初學者的角度寫的。我希望這有一定的信息性。