consultas dinámicas en dapper

c# dapper linq

Pregunta

Estoy tratando de trabajar con esto . He escrito una prueba unitaria como titular para diez, así:

[Fact]
public void TestOredGuids()
{
    // Arrange
    const string expectedSql = "SELECT * FROM Products WHERE SomeExternalForeignKey = @SomeExternalForeignKey OR Name = SomeExternalForeignKey = @SomeExternalForeignKey";

    // Act
    var result = DynamicQuery.GetDynamicQuery<Product>("Products", p => p.SomeExternalForeignKey == new Guid("28D3BCFB-9472-4141-BD88-BE5E7E1230F0") || p.SomeExternalForeignKey == new Guid("0F0DBA45-F842-4E46-9ED4-F50B5BCF0509"));

    // Assert

}

internal class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public DateTime ExpiryDate { get; set; }
    public int CategoryId { get; set; }
    public Guid SomeExternalForeignKey { get; set; }
}

Desafortunadamente, siempre recibo:

Additional information: 'System.Linq.Expressions.NewExpression' does not contain a definition for 'Value'

en el método WalkTree. ¿Estoy usando GetDynamicQuery incorrectamente?

Si hay alguna otra implementación de mapeadores dinámicos de sql como este para dapper, agradecería cualquier sugerencia. ¡Gracias!

Respuesta popular

Por lo que veo en el código fuente del componente que está tratando de usar, espera que el operando correcto de la expresión sea una ConstantExpression (aunque por alguna razón desconocida el autor está usando dynamic y espera una propiedad Value ), para hacer funciona, modifica tu código de la siguiente manera

var someExternalForeignKey1 = new Guid("28D3BCFB-9472-4141-BD88-BE5E7E1230F0");
var someExternalForeignKey2 = new Guid("0F0DBA45-F842-4E46-9ED4-F50B5BCF0509");
var result = DynamicQuery.GetDynamicQuery<Product>("Products", p => p.SomeExternalForeignKey == someExternalForeignKey1 || p.SomeExternalForeignKey == someExternalForeignKey2);

Actualización: Resulta que lo anterior tampoco funciona, porque por supuesto produce un cierre que no es ConstantExpression . Para que funcione (así como su código original), aquí están las modificaciones requeridas de la clase DynamicQuery

private static void WalkTree(BinaryExpression body, ExpressionType linkingType,
                             ref List<QueryParameter> queryProperties)
{
    if (body.NodeType != ExpressionType.AndAlso && body.NodeType != ExpressionType.OrElse)
    {
        string propertyName = GetPropertyName(body);
        var propertyValue = GetPropertyValue(body.Right);
        string opr = GetOperator(body.NodeType);
        string link = GetOperator(linkingType);

        queryProperties.Add(new QueryParameter(link, propertyName, propertyValue, opr));
    }
    else
    {
        WalkTree((BinaryExpression)body.Left, body.NodeType, ref queryProperties);
        WalkTree((BinaryExpression)body.Right, body.NodeType, ref queryProperties);
    }
}

private static object GetPropertyValue(Expression source)
{
    var constantExpression = source as ConstantExpression;
    if (constantExpression != null)
        return constantExpression.Value;
    var evalExpr = Expression.Lambda<Func<object>>(Expression.Convert(source, typeof(object)));
    var evalFunc = evalExpr.Compile();
    var value = evalFunc();
    return value;
}

Pero tenga en cuenta que toda la clase (como afirma el autor) es solo un ejemplo, y por ejemplo asigna solo un parámetro (por lo tanto, un valor) por propiedad, por lo que para hacerlo realmente útil, el método GetDynamicQuery necesita trabajo adicional. Puede probar este en su lugar. Espero que ayude.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué