如何使用Dapper与条件StringBuilder查询?

时间:2016-04-08 08:59:39

标签: c# dapper

我正在尝试构建一个动态查询字符串并将其应用于dapper(以某种方式给出类似的"感觉"实体框架可选" php app/console cache:clear --env=prod --no-debug&#34 ;功能):

构建查询字符串

.include(x=>x.XXX)

处理查询

var query = new StringBuilder();
query.Append(" select * from test_post p ");
if (validIncludesToPerform[0]) 
              query.Append(" left join sys_user u on u.Id = p.CreatorId ");
if (validIncludesToPerform[1]) 
              query.Append(" left join test_poststatus s on s.Id = p.StatusId ");
query.Append(" where p.Id = @Id; ");

var isQueryMultiple = false;
if (validIncludesToPerform[2])
{
    isQueryMultiple = true;
    query.Append(" select * from test_postnote n where n.PostId = @Id; ");
}
if (validIncludesToPerform[3])
{
    isQueryMultiple = true;
    query.Append(@" select * 
                   from test_post_tag pt 
                   left join test_tag t on t.Id = pt.TagId 
                   where pt.PostId = @Id; ");
}

重要说明: Dapper假设您的Id列已命名为" Id"或者" id",如果您的主键不同,或者您想要在" Id"以外的位置拆分宽行,请使用可选的' splitOn'参数。这意味着在我的情况下,我不必指定" Id,Id"因为这部分已经是隐含的。

  • 处理Post pst; if (isQueryMultiple) { using (var multi = Connection.QueryMultiple(query.ToString(), new { Id = id })) { pst = multi.Read<Post, User, PostStatus, Post>((post, user, status) => { if (post == null) return null; if (user != null) post.Creator = user; if (status != null) post.Status = status; return post; }).FirstOrDefault(); if (pst != null && validIncludesToPerform[2]) pst.Notes = multi.Read<PostNote>().ToList(); if (pst != null && validIncludesToPerform[3]) pst.PostTags = multi.Read<PostTag, Tag, PostTag>((pTag, tag) => { if (pTag == null) return null; if (tag != null) pTag.Tag = tag; return pTag; }).ToList(); } } else { pst = Connection.Query<Post, User, PostStatus, Post> (query.ToString(), (post, user, status) => { if (post == null) return null; if (user != null) post.Creator = user; if (status != null) post.Status = status; return post; }, new { Id = id }).FirstOrDefault(); } PostNotes的部分工作正常。
  • 帖子何时是&#34;包括&#34; PostTagsUser也正常运作。
  • 如果 FAILS ,当我尝试加载Status&#34;空&#34;或者只是UserUser ...

错误消息:&#34;当使用多映射API时,如果您拥有Id \ r \ n \ n *参数名称以外的其他键,请确保设置splitOn参数:splitOn&#34;

原因:使用泛型意味着查询将接收&#34; 3部分&#34;但它只是收到一个较低的数字....

难看的解决方案: 我知道如果我只是将StatusStatus分隔到每个独立查询中,这会有效:

User

但由于此信息类似于1对1的关系,我相信单个查询更好。所以,我试图避免使用这个解决方案。

我也不希望列出所有可能的泛型签名组合,如:

  • if (validIncludesToPerform[0]) query.Append(@" select u.* from sys_user u right join test_post p on u.Id = p.CreatorId where p.Id = @Id;"); if (validIncludesToPerform[1]) query.Append(@" select ps.* from test_poststatus ps right join test_post p on ps.Id = p.StatusId where p.Id = @Id;");
  • Connection.Query<Post, User, PostStatus, Post>
  • Connection.Query<Post, User, Post>
  • Connection.Query<Post, PostStatus, Post>

一旦我开始向这个类添加更多的1to1关系,这种方法就不友好了。

我该如何解决这个问题?

0 个答案:

没有答案