我正在尝试构建一个动态查询字符串并将其应用于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
的部分工作正常。PostTags
和User
也正常运作。Status
&#34;空&#34;或者只是User
或User
... 错误消息:&#34;当使用多映射API时,如果您拥有Id \ r \ n \ n *参数名称以外的其他键,请确保设置splitOn参数:splitOn&#34;
原因:使用泛型意味着查询将接收&#34; 3部分&#34;但它只是收到一个较低的数字....
难看的解决方案:
我知道如果我只是将Status
和Status
分隔到每个独立查询中,这会有效:
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关系,这种方法就不友好了。
我该如何解决这个问题?