c# - 这是使用 Dapper 的正确方法还是我做错了?

标签 c# linq dapper

我试图摆脱 Entity Framework ,因为我必须在我们的解决方案中支持除 SQL Server 数据库之外的 HANA 数据库。

我正在对 dapper 进行一些研究,因此我创建了一个包含一些虚构场景的快速测试环境。

我有以下类似于我的数据库模式的 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);

            }
        }
    }
}

这样做的好处是您只需访问数据库一次,然后在内存中处理所有内容。

但是,如果您要检索非常大的数据(并且来自远程位置),这可能会影响性能和内存瓶颈。最好仔细研究这种方法,并在可能的情况下尝试某种异步处理和/或分页。

关于c# - 这是使用 Dapper 的正确方法还是我做错了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41358302/

相关文章:

c# - 如何将 LINQ 查询中的 "var"填充到同一个数据表中?

entity-framework - EF Core 以升级后可以翻译的形式重写查询

dapper - 无论如何要遍历 Dapper DynamicParameters 对象吗?

c# - Dynamic Func<> for Dapper query map

c# - 如何获取长字符串并将其滚动到 15 个字符的文本控件/标签中?

c# - 访问远程数据库——最佳实践

c# - 使用 LINQ 对 ListBox ListItems 进行排序?

c# - 使用 ToList 的异步、等待和任务

c# - 如何创建一个需要继承抽象类的类型的变量?

c# - 如果我尝试选择一些数据 : 'windows-1252' is not a supported encoding name,我会收到此错误