[英]Is this the right way of using Dapper or am I doing it all wrong?
我正試圖擺脫實體框架,因為除了我們的解決方案中的SQL服務器數據庫之外,我必須支持HANA數據庫。
我正在用小巧玲瓏做一些研究,所以我用一些虛構的場景創建了一個快速測試環境。
我有以下POCO類似於我的數據庫架構(我有更多,但我限於顯示這些為簡單):
public class Adopter
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public State State { get; set; }
public int StateId { get; set; }
public string Zip { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public IEnumerable<Pet> Pets { get; set; }
}
public class State
{
public int Id { get; set; }
public string Name { get; set; }
public string Abreviation { get; set; }
}
public class Pet
{
public int Id { get; set; }
public string IdTag { get; set; }
public string Name { get; set; }
public DateTime AdmitionDate { get; set; }
public Status Status { get; set; }
public int StatusId { get; set; }
public string Notes { get; set; }
public DateTime AdoptionDate { get; set; }
public bool IsAdopted { get; set; }
public int? AdopterId { get; set; }
public int Age { get; set; }
public decimal Weight { get; set; }
public string Color { get; set; }
public Breed Breed { get; set; }
public int BreedId { get; set; }
public Gender Gender { get; set; }
public int GenderId { get; set; }
public IEnumerable<PetImage> PetImages { get; set; }
}
public class Status
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Gender
{
public int Id { get; set; }
public string Name { get; set; }
}
我在存儲庫中使用以下命令返回所有采用者的列表:
using (SqlConnection connection = new SqlConnection(_connectionString))
{
var adopters = connection.Query<Adopter>("SELECT a.* FROM Adopters a");
foreach (var adopter in adopters)
{
adopter.State = connection.QueryFirst<State>("Select s.* FROM States s WHERE s.Id = @Id", new { Id = adopter.StateId });
adopter.Pets = connection.Query<Pet>("Select p.* FROM Pets p WHERE p.AdopterId = @Id", new { Id = adopter.Id });
foreach (var pet in adopter.Pets)
{
pet.Status = connection.QueryFirst<Status>("Select s.* FROM Status s WHERE s.Id = @Id", new { Id = pet.StatusId });
pet.Gender = connection.QueryFirst<Gender>("Select g.* FROM Genders g WHERE g.Id = @Id", new { Id = pet.GenderId });
}
}
return adopters;
}
如您所見,我正在基於前一個POCO單獨檢索每個POCO的數據,並在代碼中手動執行聯接。
這是正確的方法嗎?或者我應該使用多個連接進行大查詢並通過dapper和LINQ以某種方式映射結果?
您實際解決方案的一個可能的改進是通過使用QueryMultiple擴展,如下所示:
using (SqlConnection connection = new SqlConnection(_connectionString))
{
string query = @"SELECT * FROM Adopters;
SELECT * FROM States;
SELECT * FROM Pets;
SELECT * FROM Status;
SELECT * FROM Genders;";
using (var multi = connection.QueryMultiple(query, null))
{
var adopters = multi.Read<Adopter>();
var states = multi.Read<State>();
var pets = multi.Read<Pet>();
var statuses = multi.Read<Status>();
var genders = multi.Read<Gender>();
foreach (Adopter adp in adopters)
{
adp.State = states.FirstOrDefault(x => x.Id == adp.StateID);
adp.Pets = pets.Where(x => x.IsAdopted &&
x.AdopterID.HasValue &&
x.AdopterID.Value == adp.AdopterID)
.ToList();
foreach(Pet pet in adp.Pets)
{
pet.Status = statuses.FirstOrDefault(x => x.Id == pet.StatusID);
pet.Gender = genders.FirstOrDefault(x => x.Id == pet.GenderID);
}
}
}
}
這里的好處是您只需一次訪問數據庫,然后處理內存中的所有內容。
但是,如果你有一個非常大的數據要檢索(並且從遠程位置),這可能是性能損失和內存瓶頸。 最好密切關注這種方法,並盡可能嘗試某種異步處理和/或分頁。
我不喜歡消極,但是......不要這樣做! 甚至不要這樣想。 你想轉儲EF,但是你想通過模擬EF來進入陷阱。 您的應用程序和數據庫之間的橋梁不是一直可以構建的,無論出於何種目的。 具體來說,你不應該真的帶回整個表,當然不要在每一行循環並發出更多的查詢。 您可能會受到不公正的批評,您只是在測試工具! 如果是這樣,或許告訴我們您正在研究的工具的哪個方面,我們將重點關注它。
Dapper或QueryFirst極大地簡化了運行查詢並消耗結果,因此只需在需要時就可以恢復所需內容。 然后對於手頭的具體工作進行反規范化。 為什么查詢中沒有連接 ? RDBMS非常棒,而且非常擅長加入。 如果您正在加入數據庫之外的數據,那么瘋狂是唯一的一個詞,即使Linq為您提供了超級(類似sql)的語法。 1表對應1類的不假思索的假設是許多問題的開始。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.