J'essaie de construire une chaîne de requête dynamique et de l'appliquer sur dapper ( donnant en quelque sorte une sensation similaire à la fonctionnalité optionnelle " .include(x=>x.XXX)
Entity Framework ):
Construire une chaîne de requête
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; ");
}
Requête processus
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();
}
Remarque importante: Dapper suppose que vos colonnes Id sont nommées "Id" ou "id", si votre clé primaire est différente ou si vous souhaitez diviser la ligne large au point autre que "Id", utilisez le paramètre facultatif "splitOn". Cela signifie que dans mon cas, je ne dois PAS spécifier "Id, Id" car cette partie est déjà implicite.
PostNotes
ou les PostTags
fonctionne PostTags
. User
"inclut" l' User
et le Status
fonctionne bien aussi. User
"vide" ou simplement avec l' User
ou le Status
... Message d'erreur: "Lors de l'utilisation des API de mappage multiple, veillez à définir le paramètre splitOn si vous avez des clés autres que Id \ r \ nNom du paramètre: splitOn"
Raison: L'utilisation des génériques implique que la requête va recevoir "3 parties" mais qu'elle ne fait que recevoir un nombre inférieur ....
De mauvaises solutions: Je sais que cela fonctionnerait si je séparais simplement le Status
et l' User
dans chaque requête indépendante:
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;");
mais comme cette information est comme une relation 1 à 1, je crois qu'une seule requête est meilleure. J'essaie donc d'éviter d'utiliser cette solution.
Je ne veux pas non plus avoir une liste de toutes les combinaisons possibles de la signature générique comme:
Connection.Query<Post, User, PostStatus, Post>
Connection.Query<Post, User, Post>
Connection.Query<Post, PostStatus, Post>
Connection.Query<Post>
Cette approche n'est tout simplement pas conviviale dès que je commence à ajouter plus de relations 1to1 à cette classe.
Comment puis-je réparer cela?
J'ai été en mesure de trouver une approche "en quelque sorte" moins mauvaise:
var query = new StringBuilder();
query.Append(" select * from test_post p ");
query.Append(validIncludesToPerform[0]
? " left join sys_user u on u.Id = p.CreatorId "
: " left join sys_user u on 1 = 0 ");
query.Append(validIncludesToPerform[1]
? " left join test_poststatus s on s.Id = p.StatusId "
: " left join test_poststatus s on 1 = 0 ");
query.Append(" where p.Id = @Id; ");
Je laisserai cette réponse pour le moment en attendant de meilleures alternatives ....