簡體   English   中英

這是使用Dapper的正確方法還是我做錯了?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM