0

任何有关在使用轻风时如何使用存储过程的链接示例,主要是对找出如何提取分页参数和设置 inlinecount 值感兴趣,因为存储过程将返回该值并获取分页参数。

IE

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

SP_Input_Para2 等等....

对于更新类似

    function Update(string SP_Input_Param1, string SP_Input_Param2 etc)

然后是一些如何配置 Breeze 来告诉它应该在服务器上使用以下函数来获取和更新、删除、插入等。

或者更好的方法是 For Get 使用 Request 和 Response 作为自定义结构

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;
        }

现在您可能需要在客户端上提供一个函数来映射集合

4

2 回答 2

2

要从微风请求中查询信息,请尝试将此作为您的 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);
        }

Tips:如果$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 使用这些结果的存储过程吗?我目前运行一个存储过程,它IQueryable在一次 SQL 往返中返回 23 。

祝你好运!

(编辑)

如果您在存储过程中手动应用 $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 将微风过滤器应用于 MyEntityType 的空白 IQueryable,然后使用上面链接中的代码将微风请求呈现到 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;
}
/* */
于 2017-01-02T15:50:50.150 回答
1

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

于 2013-01-06T18:09:48.347 回答