我可以使用Dapper映射具有多个关系的SQL表吗?

时间:2019-04-09 12:52:42

标签: c# sql sql-server database dapper

我正在开发C#WPF桌面应用程序,需要定期读取/写入SQL数据库(SQL Server)。现在,我想将数据库中的数据映射到C#中的对象。我无法使用实体框架,因此我正在通过Dapper和存储过程进行所有数据访问。

作为一个例子,我已经为这个示例数据库建模

enter image description here

C#对象看起来与此类似。

public class Manager {

   public string Name { get; set; }
   public string Phone { get; set; }
   public List<Facility> Facilities {get; set;}
} 

public class City {

   public string Name { get; set; }
   public string Description{ get; set; }
   public List<Facility> Facilities {get; set;}
} 

public class Facility {

   public string Name { get; set; }
   public string Description{ get; set; }
} 

我尝试使用拍板自动映射器映射数据,但是it didn't可以工作。我可以使用Dapper映射所有这些吗?我什至需要将每个表及其关系映射到C#中的类吗?还是我可以编写一个存储过程来返回所有已匹配的条目,并创建一个将所有数据作为属性的大类?

1 个答案:

答案 0 :(得分:1)

您可以使用Dapper使其正常运行,并且有多种选择:

第一个选项

您可以查询父实体,然后查询所有子实体。该代码将如下所示:

var manager = await connection.QueryFirstOrDefaultAsync<Manager>("SELECT * FROM Manager AS m WHERE m.Name = @name", new {name = name}); // use your query and your parameters

manager.Facilities = await connection.QueryAsync<Manager>("SELECT * FROM Facilities AS f WHERE f.ManagerId = @managerId", new {managerId = manager.ManagerId}); 

// use similar queries to get Cities

第二个选项

您可以使用multimapping获取多个实体(但您应该知道,它最多可以查询7个从属实体-对于您的情况就足够了):

public async Task<IEnumerable<Manager>> GetManagerWithFacilitiesByManagerName(string name)
{
    var managersDictionary = new Dictionary<int, Manager>();

    await connection.Query<Manager, Facility, Manager>(
       @"SELECT * 
         FROM Manager AS m 
         INNER JOIN Facilities as f ON f.ManagerId = m.ManagerId
         WHERE m.Name = @name", 
       (manager, facility) => 
       { 
           Manager managerEntity;

           if (managersDictionary.ContainsKey(manager.ManagerId)
           {
               managerEntity = managersDictionary[manager.ManagerId];
           } 
           else 
           {
               managerEntity = manager;
               managerEntity.Facilities = new List<Facilities>();
               managersDictionary.Add(managerEntity.ManagerId, managerEntity);
           }

           managerEntity.Facilities.Add(facility);

           return managerEntity;
       }
       new {name = name},
       splitOn: "ManagerId,FacilityId") // properties where to split entity

    return managersDictionary.Values;    
} 

如果只想先使用Manager,请使用managersDictionary.Values.FirstOrDefault()并将返回类型更改为Task<Manager>