代码之家  ›  专栏  ›  技术社区  ›  niico

使用dapper的linq中的多对多

  •  2
  • niico  · 技术社区  · 8 年前

    我有地方,每个地方都可以有很多标签。每个标签可以被分配到许多地方。

    public class Place {
        public int Id { get; set; }
        public string PlaceName { get; set; }
    
        public IEnumerable<Tag> Tags { get; set; }
    }
    
    public class Tag {
        public int Id { get; set; }
        public string TagName { get; set; }
    }
    
    public class TagPlace {
        public int Id { get; set; }
        public PlaceId { get; set; }
        public TagId { get; set; }
    }
    

    数据库有相应的带外键的等价表。

    我想要一个地方的集合,我想要每个地方都有一个合适的标签集合。我想可能需要使用linq。

    我已经找到了关于这个的各种文章,但是它们并不完全相同/处理一个int列表,而不是两个对象集合。

    https://social.msdn.microsoft.com/Forums/en-US/fda19d75-b2ac-4fb1-801b-4402d4bd5255/how-to-do-in-linq-quotselect-from-employee-where-id-in-101112quot?forum=linqprojectgeneral

    LINQ Where in collection clause

    最好的方法是什么?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Steve    8 年前

    dapper的经典方法是在查询枚举记录时使用字典存储主对象。

    public  IEnumerable<Place> SelectPlaces()
    {
        string query = @"SELECT p.id, p.PlaceName, t.id, t.tagname
                         FROM Place p INNER JOIN TagPlace tp ON tp.PlaceId = p.Id
                         INNER JOIN Tag t ON tp.TagId = t.Id";
        var result = default(IEnumerable<Place>);
        Dictionary<int, Place> lookup = new Dictionary<int, Place>();
        using (IDbConnection connection = GetOpenedConnection())
        {
             // Each record is passed to the delegate where p is an instance of
             // Place and t is an instance of Tag, delegate should return the Place instance.
             result = connection.Query<Place, Tag, Place(query, (p, t) =>
             {
                  // Check if we have already stored the Place in the dictionary
                  if (!lookup.TryGetValue(p.Id, out Place placeFound))
                  {
                       // The dictionary doesnt have that Place 
                       // Add it to the dictionary and 
                       // set the variable where we will add the Tag
                       lookup.Add(p.Id, p);
                       placeFound = p;
                       // Probably it is better to initialize the IEnumerable
                       // directly in the class 
                       placeFound.Tags = new List<Tag>();
                  }
    
                  // Add the tag to the current Place.
                  placeFound.Tags.Add(t);
                  return placeFound;
    
              }, splitOn: "id");
              // SplitOn is where we tell Dapper how to split the record returned
              // in the two instances required, but here SplitOn 
              // is not really needed because "Id" is the default.
    
         }
         return result;
    }