SubSonic 3, dynamique de construction ou d'expression lors de l'exécution
-
27-09-2019 - |
Question
J'ai une situation où je dois construire dynamiquement une requête LINQ en fonction des choix de l'utilisateur. Si je devais générer dynamiquement sql je pouvais le faire de cette façon:
var sb = new StringBuilder();
sb.AppendLine("SELECT * FROM products p");
sb.AppendLine("WHERE p.CategoryId > 5");
// these variables are not static but choosen by the user
var type1 = true;
var type2 = true;
var type3 = false;
string type1expression = null;
string type2expression = null;
string type3expression = null;
if (type1)
type1expression = "p.productType1 = true";
if (type2)
type2expression = "p.productType2 = true";
if (type3)
type3expression = "p.productType3 = true";
string orexpression = String.Empty;
foreach(var expression in new List<string>
{type1expression, type2expression, type3expression})
{
if (!String.IsNullOrEmpty(orexpression) &&
!String.IsNullOrEmpty(expression))
orexpression += " OR ";
orexpression += expression;
}
if (!String.IsNullOrEmpty(orexpression))
{
sb.AppendLine("AND (");
sb.AppendLine(orexpression);
sb.AppendLine(")");
}
// result:
// SELECT * FROM products p
// WHERE p.CategoryId > 5
// AND (
// p.productType1 = true OR p.productType2 = true
// )
Maintenant, je dois créer une requête LINQ de la même manière.
Cela fonctionne bien avec subsonique
var result = from p in db.products
where p.productType1 == true || p.productType2 == true
select p;
Je l'ai essayé avec PredicateBuilder http://www.albahari.com/nutshell/predicatebuilder.aspx mais qui génère une exception avec subsonique.
var query = from p in db.products
select p;
var inner = PredicateBuilder.False<product>();
inner = inner.Or(p => p.productType1 == true);
inner = inner.Or(p => p.productType2 == true);
var result = query.Where(inner);
l'exception qui est levée: NotSupportedException: The member 'productType1' is not supported
à SubSonic.DataProviders.MySQL.MySqlFormatter.VisitMemberAccess
.
Tout le monde a une idée comment obtenir cette requête au travail:
La solution
Peut-être Dynamic LINQ sera utile?
Autres conseils
Voici un exemple d'utilisation, tel que demandé par geocine. Elle exige dynamique LINQ.
var productTypes = new int[] {1,2,3,4};
var query = from p in db.products
select p;
if (productTypes.Contains(1))
query.Add("productType1 = @0");
if (productTypes.Contains(2))
query.Add("productType2 = @0");
if (productTypes.Contains(3))
query.Add("productType3 = @0");
if (productTypes.Contains(4))
query.Add("productType4 = @0");
if (productTypes.Count > 0)
{
string result = String.Join(" OR ", productTypes);
query = query.Where("(" + result + ")", true);
}
var result = from p in query
select new {Id = p.ProductId, Name = p.ProductName };
il semble akward mais cela fonctionne.