繁体   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