如何使用接受分页参数的存储过程

时间:2013-01-05 16:13:52

标签: breeze

使用breeze时如何使用存储过程的任何链接示例,主要是想知道如何提取Paging参数和设置inlinecount值,因为存储过程将返回该值并获取分页参数。

I.E

    function GetData(int Pageindex,int PageSize, string SP_Input_Para1,string 

SP_Input_Para2等......

同样适用于Update

    function Update(string SP_Input_Param1, string SP_Input_Param2 etc)

然后有些人如何配置Breeze告诉它应该在服务器上使用以下功能来获取& amp;更新,删除,插入等。

或者更好的方法是 用于获取使用请求和响应作为自定义结构

i.e
    public class MyResponse
{
    public IEnumerable<Object> Results { get; set; }
    public string Message { get; set; }


}
public class MyRequest
{
    public PagingInfo pageInfo { get; set; }
    public ParameterInfo Parameters { get; set; }
}


public class PagingInfo
{
    public int PageIndex { get; set; }
    public int PageSize { get; set; }
}

public class ParameterInfo
{
    public string Parameter1 { get; set; }
    public string Parameter2 { get; set; }
    public string Parameter3 { get; set; }
}

then use

public MyResponse GetData(MyResponse request)
        {
            var resp = new MyResponse();
            var lst = new List<object>();
            // do oyur work
            resp.Results= lst;

            return lst;
        }

现在您可能需要在客户端上提供一个映射集合的功能

2 个答案:

答案 0 :(得分:2)

要查询breeze请求中的信息,请尝试将其作为GET方法。这假设GetMyEntityType返回数据上下文中的实体。

[HttpGet]
[EnableBreezeQuery(MaxExpansionDepth = 0)]
public QueryResult GetMyEntityType(ODataQueryOptions<MyEntityType> options)
{
... your server method
}

您需要了解的关于微风请求的所有内容都在此对象中。起初我想知道如何在这个对象中包含其他参数,但没有必要 - 参数在对象内部。

为了让你跳过并试试,试试这个......

foreach (var queryParam in options.Request.Properties.FirstOrDefault(x => x.Key == "MS_QueryNameValuePairs").Value as System.Collections.Generic.KeyValuePair<string, string>[])
        {
            if (queryParam.Key == "$skip")
                int.TryParse(queryParam.Value, out skip);
            if (queryParam.Key == "$top")
                int.TryParse(queryParam.Value, out top);
        }

提示:    如果$ skip为0,则它​​可能不在请求参数中。将其默认为0。    Breeze使用$ top,而不是$ take。

您可以使用

调用存储过程
DB.ObjectContext.ExecuteStoreQuery<MyEntityType>(query).ToList()

只要查询返回MyEntityType类型的实体集,查询就可以是任何内容。 EXEC MyStoredProc param1,param2,或者你甚至可以构建动态SQL。

要返回自己的inlineCount,请使用QueryResult返回类型:

        return new QueryResult()
        {
            InlineCount = myInlineCount,
            Results = DB.ObjectContext.ExecuteStoreQuery<MyEntityType>(query).ToList()
        };

提取过滤器并非易事。我找到了一个解决方案并对其进行了修改以添加递归并对其进行调整以处理Breeze请求。这些是帮助方法和帮助类,您需要提取它们。

    private void ProcessUnaryOperator(UnaryOperatorNode unaryOperator, List<ODataFilter> filterList)
    {
        if (unaryOperator != null)
        {
            if (unaryOperator.Operand != null && unaryOperator.Operand.GetType().FullName == "Microsoft.Data.OData.Query.SemanticAst.BinaryOperatorNode")
            {
                ProcessBinaryOperator(unaryOperator.Operand as BinaryOperatorNode, filterList);
            }
        }
    }

    private void ProcessBinaryOperator(BinaryOperatorNode binaryOperator, List<ODataFilter> filterList)
    {
        if (binaryOperator != null)
        {
            if (binaryOperator.Left != null && binaryOperator.Left.GetType().FullName == "Microsoft.Data.OData.Query.SemanticAst.BinaryOperatorNode")
                ProcessBinaryOperator(binaryOperator.Left as BinaryOperatorNode, filterList);

            if (binaryOperator.Right != null && binaryOperator.Right.GetType().FullName == "Microsoft.Data.OData.Query.SemanticAst.BinaryOperatorNode")
                ProcessBinaryOperator(binaryOperator.Right as BinaryOperatorNode, filterList);

            if (binaryOperator.Left != null && binaryOperator.Left.GetType().FullName == "Microsoft.Data.OData.Query.SingleValueFunctionCallNode")
            {
                var singleValueFunctionCallNode = binaryOperator.Left as SingleValueFunctionCallNode;

                var property = (singleValueFunctionCallNode.Arguments.FirstOrDefault() as SingleValuePropertyAccessNode ?? singleValueFunctionCallNode.Arguments.LastOrDefault() as SingleValuePropertyAccessNode) ;
                var constant = (singleValueFunctionCallNode.Arguments.FirstOrDefault() as ConstantNode ?? singleValueFunctionCallNode.Arguments.LastOrDefault() as ConstantNode);

                var lt = string.Empty;
                switch (singleValueFunctionCallNode.Name)
                {
                    case "startswith":
                        lt = constant.Value.ToString() + "%";
                        break;
                    case "endswith":
                        lt = "%" + constant.Value.ToString();
                        break;
                    case "substringof":
                        lt = "%" + constant.Value.ToString() + "%";
                        break;
                    case "equal":
                        lt = constant.Value.ToString();
                        break;
                }

                if (property != null && property.Property != null && constant != null && constant.Value != null)
                    filterList.Add(new ODataFilter(property.Property.Name, binaryOperator.OperatorKind.ToString(), lt, property, constant));
            }

            if (binaryOperator.Left != null && binaryOperator.Left.GetType().FullName == "Microsoft.Data.OData.Query.SingleValuePropertyAccessNode")
            {
                var property = binaryOperator.Left as SingleValuePropertyAccessNode ?? binaryOperator.Right as SingleValuePropertyAccessNode;
                var constant = binaryOperator.Left as ConstantNode ?? binaryOperator.Right as ConstantNode;
                var lt = constant.Value.ToString();

                if (property != null && property.Property != null && constant != null && constant.Value != null)
                    filterList.Add(new ODataFilter(property.Property.Name, binaryOperator.OperatorKind.ToString(), lt, property, constant));
            }
        }
    }

    public class ODataFilter
    {
        public ODataFilter(string prop, string op, string lt, SingleValuePropertyAccessNode pn, ConstantNode cn)
        {
            this.Property = prop;
            this.Operator = op;
            this.LiteralText = lt;
            this.PropertyNode = pn;
            this.ConstantNode = cn;
        }

        public string Property { get; set; }
        public string Operator { get; set; }
        public string LiteralText { get; set; }
        public SingleValuePropertyAccessNode PropertyNode { get; set; }
        public ConstantNode ConstantNode { get; set; }
    }

这是提取过滤器的调用代码:

        List<ODataFilter> filterList = new List<ODataFilter>();

        // Not Equal (Unary Operators)
        if (options.Filter != null && options.Filter.FilterClause != null && options.Filter.FilterClause.Expression.GetType().Name == "UnaryOperatorNode")
            ProcessUnaryOperator(options.Filter.FilterClause.Expression as UnaryOperatorNode, filterList);

        // Equal (Binary Operators)
        if (options.Filter != null && options.Filter.FilterClause != null && options.Filter.FilterClause.Expression.GetType().Name == "BinaryOperatorNode")
            ProcessBinaryOperator(options.Filter.FilterClause.Expression as BinaryOperatorNode, filterList);

这是USING的一部分

using Microsoft.Data.OData.Query; 
using System.Web.Http.OData.Query; 
using Microsoft.Data.OData.Query.SemanticAst;

您是否知道可以执行返回多个结果集的存储过程并使用MARS使用这些结果?我目前运行的存储过程在一次SQL往返中返回23 IQueryable

祝你好运!

(编辑)

如果您在存储过程中手动应用$ skip和$ top,Breeze将尝试再次对结果集应用它们。在这种情况下,我只是将skip和top作为参数发送,而不是使用$ skip和$ top。顺便说一下,这个bug需要7个小时才能找到。

此链接:https://www.stevefenton.co.uk/2015/07/getting-the-sql-query-from-an-entity-framework-iqueryable/显示如何将IQueryable对象转换为T-SQL。使用options.Filter.ApplyTo将breeze过滤器应用于空白IQueryable of MyEntityType,然后使用上面链接中的代码将breeze请求呈现到TSQL中。

// Determine the where clause 
var whereClause = options.Filter == null ? "" : ToTraceString<MyEntityType>(
    options.Filter.ApplyTo(
        (from x in DB.Context.MyEntityTypes select x),
        new ODataQuerySettings()) as IQueryable<MyEntityType>)
    .Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries).Where(x => x.Trim().StartsWith("WHERE")).FirstOrDefault().Trim();

/* Steve Fenton, https://www.stevefenton.co.uk/2015/07/getting-the-sql-query-from-an-entity-framework-iqueryable/
 * July 24, 2015
 * */
private static string ToTraceString<T>(IQueryable<T> query)
{
    var internalQueryField = query.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Where(f => f.Name.Equals("_internalQuery")).FirstOrDefault();
    var internalQuery = internalQueryField.GetValue(query);
    var objectQueryField = internalQuery.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Where(f => f.Name.Equals("_objectQuery")).FirstOrDefault();
    var objectQuery = objectQueryField.GetValue(internalQuery) as System.Data.Entity.Core.Objects.ObjectQuery<T>;
    return ToTraceStringWithParameters<T>(objectQuery);
}
private static string ToTraceStringWithParameters<T>(System.Data.Entity.Core.Objects.ObjectQuery<T> query)
{
    System.Text.StringBuilder sb = new StringBuilder();
    string traceString = query.ToTraceString() + Environment.NewLine;
    foreach (var parameter in query.Parameters)
        traceString = traceString.Replace("@" + parameter.Name, "'" + parameter.Value.ToString() + "'");
    return traceString;
}
/* */

答案 1 :(得分:1)

这是一个很好的问题,但我们还没有任何使用微风使用存储过程的例子,尽管这是非常可行的。请将此添加到Breeze User Voice并投票赞成。我们认真对待您的反馈。