SharePoint CAML查询转换为T-SQL

3
我希望将一个CAML查询转换成T-SQL。我的SharePoint网站还有一个数据仓库(SQL Server 2005),其中保存着相同的数据(通过SPList EventReceivers:ItemAdded,ItemUpdated进行填充)。
我正在处理列表的增长以及显示列表数据的自定义Web部件的速度。我希望使用数据仓库来显示我们的列表内容,然后删除已完成工作流程的SPLists中的项目。
目前,自定义Web部件的用户可以选择SPView来按照他们想要的方式显示内容(例如过滤、排序和仅显示必要的列)。我希望保留这个功能,并希望将视图的CAML查询转换为T-SQL,以对数据仓库进行查询。
<Query>
  <Where>
    <Or>
      <Eq>
        <FieldRef Name="ContentType" />
        <Value Type="Text">My Content Type</Value>
      </Eq>
      <IsNotNull>
        <FieldRef Name="Description" />
      </IsNotNull>
    </Or>
  </Where>
  <Order>
    <FieldRef Name="Author" />
    <FieldRef Name="AuthoringDate" />
    <FieldRef Name="AssignedTo" Ascending="True" />
  </Order>
  <Group>
    <FieldRef Name="Title" />
  </Group>
</Query>

to

WHERE ContentType="My Content Type"
OR Description<>null
GROUPBY Title DESC
ORDERBY Author, AuthoringDate, AssignedTo ASC

有人知道如何做到这一点吗?或者有其他解决此问题的替代建议吗?我找到了多种将T-SQL转换为CAML查询的解决方案,但没有相反的情况(即http://yacamlqt.codeplex.com/--这也是我检索示例的地方)。

谢谢!

7个回答

2
我希望能找到一段代码,将CAML转换成SQL,以便构建自己的SQL语句来访问数据。我的主要项目是构建SharePoint功能区扩展程序,将列表(内部和外部)内容导出为CSV,并在外部列表中绕过外部内容类型(BCS)强制执行的限制(2000)。我正在使用元数据存储和安全存储中的信息来构建连接字符串并直接访问数据库。当我需要改进代码以包括筛选器时,最终我构建了自己的方法来获取视图查询的“Where”部分并将其转换为类似SQL的Where语句:输入:在我的情况下,它是一个SPView对象,但可以很容易地转换为使用字符串。我从中提取“CAML”类似的查询。
"<Where>
  <And>
    <Or>
      <Geq>
        <FieldRef Name=\"Microfilm\" />
        <Value Type=\"Text\">10</Value>
      </Geq>
      <Leq>
        <FieldRef Name=\"Microfilm\" />
        <Value Type=\"Text\">50</Value>
      </Leq>
    </Or>
    <BeginsWith>
      <FieldRef Name=\"Title\" />
      <Value Type=\"Text\">Ice</Value>
    </BeginsWith> 
  </And>
</Where>"

输出:

"(Microfilm >= 10 OR Microfilm <= 50) AND Title LIKE 'Ice%'"

以下是方法:

该方法将从视图查询中提取“Where”节点,将其传递给一个方法进行处理,并返回类似于SQL语句的结果。

    private static string ViewQueryToSqlWhere(SPView v)
    {
        string sqlWhere = string.Empty;
        XmlDocument xmlDoc = new XmlDocument();
        XmlNodeList nodeList;

        //Add <Query> around the SPView.Query since a valid XML document requires a single root element.
        //and SPView.Query doesn't.
        xmlDoc.LoadXml("<Query>" + v.Query + "</Query>");

        nodeList = xmlDoc.GetElementsByTagName("Where");

        if (nodeList.Count == 1)
        {
            XmlNode nodeWhere = nodeList[0];

            if (nodeWhere.HasChildNodes) //Should Always be the case
            {
                StringBuilder sb = new StringBuilder();
                bool isSuccess = ProcessWhereNode(nodeWhere, ref sb);
            }
        }

        return sqlWhere;
    }

这个方法将调用另一个方法递归地遍历所有节点,获取视图查询“Where”节点中的值和运算符。它会在“OR”语句周围放置圆括号以保留操作优先级。

    private static bool ProcessWhereNode(XmlNode xmlNode, ref StringBuilder sb)
    {
        bool isSuccess = false;
        Stack<string> operatorStack = new Stack<string>();
        Queue<string> valueQueue = new Queue<string>();
        string previousOp = string.Empty;
        string strOperator = string.Empty;

        try
        {
            //Call a method to iterate "recursively" throught the nodes to get the values and operators.
            if (ProcessRecursiveWhereNode(xmlNode, "", "", ref operatorStack, ref valueQueue))
            {
                while (valueQueue.Count > 0)
                {
                    if (operatorStack.Count > 0)
                    {
                        strOperator = operatorStack.Pop();

                        //Open bracket if it's an OR operator except if the previous one was also an OR.
                        if (strOperator == "OR" && previousOp != "OR")
                            sb.Append("(");
                    }
                    else
                    {
                        strOperator = string.Empty;
                    }

                    sb.Append(valueQueue.Dequeue());

                    //Close bracket if previous OP was an OR, and it's not followed by another one
                    if (previousOp == "OR" && strOperator != "OR")
                        sb.Append(")");

                    if (strOperator != string.Empty)
                    {
                        sb.Append(" " + strOperator + " ");
                    }

                    previousOp = strOperator;
                }
            }
        }
        catch (Exception ex)
        { }

        return isSuccess;
    }

这种方法可以通过遍历每个节点来完成大部分工作:

private static bool ProcessRecursiveWhereNode(XmlNode xmlNode, string strOperatorValue, string strOperatorType, ref Stack<string> operatorStack, ref Queue<string> valueQueue)
        {
            bool isSuccess = false;
            string fieldName = string.Empty;
            string value = string.Empty;
            string thisIterationOperatorType = string.Empty;
            string thisIterationOperatorValue = string.Empty;

            try
            {
                XmlNodeList nodeList = xmlNode.ChildNodes;

                //Get Child node - Possible tags {<Or>, <And>, <Eq>, <Neq>, <Gt>, <Lt>, <Geq>, <Leq>, </BeginsWith>, <Contains>, <FieldRef>, <Value>}
                foreach (XmlNode node in nodeList)
                {
                    thisIterationOperatorType = string.Empty;
                    thisIterationOperatorValue = string.Empty;

                    //Check if it's one of these tag: <Or>, <And>, <Eq>, <Neq>, <Gt>, <Lt>, <Geq>, <Leq>, </BeginsWith>, <Contains>
                    thisIterationOperatorValue = GetOperatorString(node.Name, out thisIterationOperatorType);

                    if (thisIterationOperatorType == "statement")
                        operatorStack.Push(thisIterationOperatorValue);

                    //It's one of these tag: <Or>, <And>, <Eq>, <Neq>, <Gt>, <Lt>, <Geq>, <Leq>, </BeginsWith>, <Contains>
                    if (thisIterationOperatorValue != string.Empty)
                    {
                        ProcessRecursiveWhereNode(node, thisIterationOperatorValue, thisIterationOperatorType, ref operatorStack, ref valueQueue);
                    }
                    else //It is probably a <FieldRef> or <Value> tag.
                    {
                        if (node.Name == "FieldRef")
                            fieldName = node.Attributes["Name"].Value.ToString();
                        else if (node.Name == "Value")
                            value = node.LastChild.Value.ToString();
                    }
                }

                if (strOperatorType == "value" && strOperatorValue != string.Empty && fieldName != string.Empty && value != string.Empty)
                {
                    valueQueue.Enqueue(string.Format(strOperatorValue, fieldName, "'" + value + "'"));
                }

                isSuccess = true;
            }
            catch
            {
                isSuccess = false;
                throw;
            }

            return isSuccess;
        }

这个最后的方法可能本来可以包含在递归方法中,但是在我第一次构建代码时,将其分开更有意义,所以我保留了这种方式。它只是获取运算符的一些信息,并关联一个运算符字符串,将用于构建SQL Where语句的各个部分。
static private string GetOperatorString(string tagName, out string operatorType)
{
    string operatorString = string.Empty;

    switch (tagName)
    {
        case "Or":
            operatorString = "OR";
            operatorType = "statement";
            break;
        case "And":
            operatorString = "AND";
            operatorType = "statement";
            break;
        case "Eq":
            operatorString = "{0} = {1}";
            operatorType = "value";
            break;
        case "Neq":
            operatorString = "{0} != {1}";
            operatorType = "value";
            break;
        case "Gt":
            operatorString = "{0} > {1}";
            operatorType = "value";
            break;
        case "Lt":
            operatorString = "{0} < {1}";
            operatorType = "value";
            break;
        case "Geq":
            operatorString = "{0} >= {1}";
            operatorType = "value";
            break;
        case "Leq":
            operatorString = "{0} <= {1}";
            operatorType = "value";
            break;
        case "BeginsWith":
            operatorString = "{0} LIKE '{1}%";
            operatorType = "value";
            break;
        case "Contains":
            operatorString = "{0} LIKE '%{1}%";
            operatorType = "value";
            break;
        default:
            operatorString = string.Empty;
            operatorType = string.Empty;
            break;
    }

    return operatorString;
}

我知道它不是一个完整的转换工具,但这是个开始,现在它满足我的需求。我希望这能帮助到别人并节省他们宝贵的时间。


1

我的非常简单的类可以将字符串 SQL 转换为 CAML,例如:

CSqlToCAML.TextSqlToCAML(sql);

sql = ....

select id,evid_cislo,nazov,adresa,ulica,vec,datum_zal,datum_odos,ukoncene_dna  
from koresp  
where ((id_typ <= 3 or id_typ = 4) 
 and (datum_zal > datum_odos)) or (id > 21) 
order by nazov desc ,id asc

CAML输出是...

<Query>
<ViewFields>
 <FieldRef Name=" id" /><FieldRef Name="evid_cislo" /><FieldRef Name="nazov" />
 <FieldRef Name="adresa" /><FieldRef Name="ulica" />
 <FieldRef Name="vec" /><FieldRef Name="datum_zal" />
 <FieldRef Name="datum_odos" /><FieldRef Name="ukoncene_dna  " />
</ViewFields>
<Where>
 <Or>
  <Leq><FieldRef Name="id_typ" /><Value Type="Text">3</Value></Leq>
  <Eq><FieldRef Name="id_typ" /><Value Type="Text">4</Value></Eq>
 </Or>
 <Or>
  <Gt><FieldRef Name="datum_zal" /><Value Type="Text">datum_odos</Value></Gt>
 </Or>
 <Or>
  <Gt><FieldRef Name="id" /><Value Type="Text">21</Value></Gt>
 </Or>
</Where>
<OrderBy>
 <FieldRef Name="nazov" Ascending="FALSE" />
 <FieldRef Name="id" Ascending="TRUE" />
</OrderBy>
</Query>

类源代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace SPASMXServices.ISAPI
{
public static class CSqlToCAML
{


    public static string TextSqlToCAML(string query)
    {
        string ret = "";
        try
        {
            string[] grpsExpr = query.ToLower().Split(new string[] { "select","from","where","order by","having" }, StringSplitOptions.RemoveEmptyEntries);
            ret += TextSqlToCAML(getValueStrArr(grpsExpr, 0), 
                                 getValueStrArr(grpsExpr, 1), 
                                 getValueStrArr(grpsExpr, 2), 
                                 getValueStrArr(grpsExpr, 3), 
                                 getValueStrArr(grpsExpr, 4)
                                );
        }
        catch (Exception ex)
        {
            Log("CSqlToCAML.TextSqlToCAML() error: " + ex.Message);
        }
        return ret;
    }

    public static string TextSqlToCAML(string select, string from, string where, string orderby, string having)
    {
        string ret = "<Query>";
        try
        {
            ret += sqltocamlSelect(select);
            ret += sqltocamlWhere(where);
            ret += sqltocamlOrderBy(orderby);
        }
        catch (Exception ex)
        {
            Log("CSqlToCAML.TextSqlToCAML() error: " + ex.Message);
        }
        return ret + "</Query>";
    }


    private static string getValueStrArr(string[] strs, int index)
    {
        try
        {
            return strs[index];
        }
        catch
        {
            return "";
        }
    }

    private static string sqltocamlOrderBy(string _orderby)
    {
        string ret = "";
        try
        {
            ret += "<OrderBy>\n";
            string[] grpsExpr = _orderby.ToLower().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string expr in grpsExpr)
            {
                string val = expr.ToLower();
                string ascc = val.ToLower().Contains("asc") ? "TRUE" : val.ToLower().Contains("desc") ? "FALSE" : "TRUE";
                val = val.Replace("asc", "");
                val = val.Replace("desc", "");
                val = val.Trim();
                ret += string.Format("<FieldRef Name=\"{0}\" Ascending=\"{1}\" />\n", val,ascc).Trim();
            }
            ret += "</OrderBy>\n";
        }
        catch (Exception ex)
        {
            Log("CSqlToCAML.sqltocamlSelect() error: " + ex.Message);
        }
        return ret;
    }

    private static string sqltocamlSelect(string _select)
    {
        string ret = "";
        try
        {
            ret += "<ViewFields>\n";
            string[] grpsExpr = _select.ToLower().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string expr in grpsExpr)
            {
                ret += string.Format("<FieldRef Name=\"{0}\" />\n", expr).Trim(); 
            }
            ret += "</ViewFields>\n";
        }
        catch (Exception ex)
        {
            Log("CSqlToCAML.sqltocamlSelect() error: " + ex.Message);
        }
        return ret;
    }

    private static string sqltocamlWhere(string _where)
    {
        string ret = "", retAnd = "", retOr = "";
        try
        {
            /*
            •Eq = equal to  
            •Neq = not equal to 
            •BeginsWith = begins with 
            •Contains = contains 
            •Lt = less than 
            •Leq = less than or equal to
            •Gt = greater than 
            •Geq = greater than or equal to 
            •IsNull = is null 
            •IsNotNull = is not null
            */

            // "(id_typ = 3 or id_typ = 4) and (datum_zal > datum_odos) "
            ret += "<Where>\n";
            string[] grpsExpr = _where.ToLower().Split(new string[] { "(", ")"}, StringSplitOptions.RemoveEmptyEntries);
            foreach (string expr in grpsExpr)
            {

                if (expr.Contains("and"))
                {
                    retAnd = "";
                    foreach (string exp in expr.Split(new string[] { "and" }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        retAnd += expStr(exp);
                    }
                    if (retAnd.Length > 0)
                    {
                        ret += "<And>\n";
                        ret += retAnd;
                        ret += "</And>\n";
                    }
                }

                if (expr.Contains("or") != null)
                {
                    retOr = "";
                    foreach (string exp in expr.Split(new string[] { "or" }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        retOr += expStr(exp);
                    }
                    if (retOr.Length > 0)
                    {
                        ret += "<Or>\n";
                        ret += retOr;
                        ret += "</Or>\n";
                    }
                }
            }
            ret += "</Where>\n";
        }
        catch (Exception ex)
        {
            Log("CSqlToCAML.sqltocamlWhere() error: " + ex.Message);
        }
        return ret;
    }

    private static string expStr(string exp)
    {
        string ret = "";
        ret += propExp(exp, "=");
        ret += propExp(exp, "<>");
        ret += propExp(exp, "<");
        ret += propExp(exp, ">");
        ret += propExp(exp, "<=");
        ret += propExp(exp, ">=");
        ret += propExp(exp, "is null");
        ret += propExp(exp, "is not null");
        ret += propExp(exp, "in");
        ret += propExp(exp, "like");
        ret += propExp(exp, "between");
        return ret;
    }


    private static string propExp(string sExp, string op)
    {
        string ret = "", _op = "";
        try
        {
            if (!sExp.Contains(op))
                return "";
            sExp = sExp.Replace("'", " ");
            sExp = sExp.Replace("   "," ");
            sExp = sExp.Replace("  ", " ");                
            string[] _ops = sExp.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            string[] _opx = sExp.Split(new string[] { op }, StringSplitOptions.RemoveEmptyEntries);

            if (_ops[1] != op)
                return "";

            string name, value;
            name = sExp.Split(new string[] { op }, StringSplitOptions.RemoveEmptyEntries)[0];
            value = sExp.Split(new string[] { op }, StringSplitOptions.RemoveEmptyEntries)[1];
            value = value.Trim();
            name = name.Trim();

            while(true)
            {

                if (sExp.Contains(op) && op == "<=")
                {
                    _op = "Leq";
                    break;
                }

                if (sExp.Contains(op) && op == ">=")
                {
                    _op = "Geq";
                    break;
                }

                if (sExp.Contains(op) && op == "=")
                {
                    _op = "Eq";
                    break;
                }

                if (sExp.Contains(op) && op == "<>")
                {
                    _op = "Eq";
                    break;
                }

                if (sExp.Contains(op) && op == "<>" && sExp.Contains("null"))
                {
                    _op = "IsNotNull";
                    break;
                }

                if (sExp.Contains(op) && op == "is not null")
                {
                    _op = "IsNotNull";
                    break;
                }

                if (sExp.Contains(op) && op == "is null")
                {
                    _op = "IsNull";
                    break;
                }

                if (sExp.Contains(op) && op == "<")
                {
                    _op = "Lt";
                    break;
                }

                if (sExp.Contains(op) && op == ">")
                {
                    _op = "Gt";
                    break;
                }
                break;
            }
            if (!string.IsNullOrEmpty(_op) && !string.IsNullOrEmpty(name))
                ret += string.Format("<{0}><FieldRef Name=\"{1}\" /><Value Type=\"Text\">{2}</Value></{0}>\n", _op, name, value);
        }
        catch (Exception ex)
        {
            Log("CSqlToCAML.propExp(" + sExp + ") error: " + ex.Message);
        }
        return ret;
    }


    private static void Log(string text)
    {
        //MessageBox.Show(text);
        LOG += string.Format("[{0} - {1};\n]", DateTime.Now, text);
    }


    public static string LOG;
}
}

(bob.)


1

虽然这不是一个技术上的答案,但我觉得它是必要的。你的方法有点反向。听起来你真正想做的是将SharePoint用作数据仓库的UI。如果是这样,我建议你改变你的方法,采用本问题范围之外的几种选项之一。

在SharePoint中进行数据访问只能通过对象模型、Web服务或用户界面进行支持。任何超出此范围的交互都可能导致各种不受支持的模式,包括数据损坏、数据锁定、不同的结果集、安全访问等等。

听起来你真正需要的是BDC服务。这将允许你使用数据仓库作为中央存储,并为你提供SharePoint原生功能的列表交互。

我不确定你使用的是哪个版本,但如果你真的想直接访问数据,SQL社区中有大量关于直接访问数据的文章。还有一个LINQtoSharePoint的CodePlex项目http://linqtosharepoint.codeplex.com/,你可以使用它来支持对象,从而获得类似于SQL的功能。


谢谢Brian,我喜欢BDC服务的想法。我会研究一下。 - OzymandiasII

0

谢谢你的帮助,我也需要它,你的代码很好,但我稍微改进了一下:

  • 操作符为 null 且 isnotnull 没有被处理
  • 使用 like 操作符时有一个小错误

请注意,代码不会转义列名(根据您的数据库引擎进行转义)

这是一个静态类中的代码:

//https://dev59.com/g1bUa4cB1Zd3GeqPA7P2
public static class CAMLtoSQL
{
    public static string ViewQueryToSqlWhere(string query)
    {
        string sqlWhere = string.Empty;
        XmlDocument xmlDoc = new XmlDocument();
        XmlNodeList nodeList;

        //Add <Query> around the SPView.Query since a valid XML document requires a single root element.
        //and SPView.Query doesn't.
        xmlDoc.LoadXml("<Query>" + query + "</Query>");

        nodeList = xmlDoc.GetElementsByTagName("Where");

        if (nodeList.Count == 1)
        {
            XmlNode nodeWhere = nodeList[0];

            if (nodeWhere.HasChildNodes) //Should Always be the case
            {
                StringBuilder sb = new StringBuilder();
                bool isSuccess = ProcessWhereNode(nodeWhere, ref sb);
                sqlWhere = sb.ToString();
            }
        }

        return sqlWhere;
    }
    private static bool ProcessWhereNode(XmlNode xmlNode, ref StringBuilder sb)
    {
        bool isSuccess = false;
        Stack<string> operatorStack = new Stack<string>();
        Queue<string> valueQueue = new Queue<string>();
        string previousOp = string.Empty;
        string strOperator = string.Empty;

        try
        {
            //Call a method to iterate "recursively" throught the nodes to get the values and operators.
            if (ProcessRecursiveWhereNode(xmlNode, "", "", ref operatorStack, ref valueQueue))
            {

                // For each operator adding parenthesis before starting 
                StringBuilder sbTmp = new StringBuilder();
                operatorStack.ToList().ForEach(x => sbTmp.Append("("));
                sb.Append(sbTmp.ToString());

                while (valueQueue.Count > 0)
                {
                    if (operatorStack.Count > 0)
                    {
                        strOperator = operatorStack.Pop();

                    }
                    else
                    {
                        strOperator = string.Empty;
                    }

                    sb.Append(valueQueue.Dequeue());

                    // After each logical operation closing parenthesis 
                    if (previousOp != string.Empty)
                        sb.Append(")");

                    if (strOperator != string.Empty)
                        sb.Append(" " + strOperator + " ");

                    previousOp = strOperator;
                }
            }
            isSuccess = true;
        }
        catch (Exception)
        {
            isSuccess = false;
        }

        return isSuccess;
    }

    private static bool ProcessRecursiveWhereNode(XmlNode xmlNode, string strOperatorValue, string strOperatorType, ref Stack<string> operatorStack, ref Queue<string> valueQueue)
    {
        bool isSuccess = false;
        string fieldName = string.Empty;
        string value = string.Empty;
        string thisIterationOperatorType = string.Empty;
        string thisIterationOperatorValue = string.Empty;

        try
        {
            XmlNodeList nodeList = xmlNode.ChildNodes;

            //Get Child node - Possible tags {<Or>, <And>, <Eq>, <Neq>, <Gt>, <Lt>, <Geq>, <Leq>, </BeginsWith>, <Contains>, <IsNotNull>, <IsNull>, <FieldRef>, <Value>}
            foreach (XmlNode node in nodeList)
            {
                thisIterationOperatorType = string.Empty;
                thisIterationOperatorValue = string.Empty;

                //Check if it's one of these tag: <Or>, <And>, <Eq>, <Neq>, <Gt>, <Lt>, <Geq>, <Leq>, </BeginsWith>, <Contains>, <IsNotNull>, <IsNull>
                thisIterationOperatorValue = GetOperatorString(node.Name, out thisIterationOperatorType);

                if (thisIterationOperatorType == "statement")
                    operatorStack.Push(thisIterationOperatorValue);

                //It's one of these tag: <Or>, <And>, <Eq>, <Neq>, <Gt>, <Lt>, <Geq>, <Leq>, </BeginsWith>, <Contains>, <IsNotNull>, <IsNull>
                if (thisIterationOperatorValue != string.Empty)
                {
                    ProcessRecursiveWhereNode(node, thisIterationOperatorValue, thisIterationOperatorType, ref operatorStack, ref valueQueue);
                }
                else if (strOperatorType != "statement") //It is probably a <FieldRef> or <Value> tag.
                {
                    if (node.Name == "FieldRef")
                        fieldName = node.Attributes["Name"].Value.ToString();
                    else if (node.Name == "Value")
                        value = node.LastChild.Value.ToString();
                }
            }

            if ((strOperatorType == "value" && strOperatorValue != string.Empty && fieldName != string.Empty && value != string.Empty)
                ||
                (strOperatorType == "is" && strOperatorValue != string.Empty && fieldName != string.Empty))
            {
                // if contains a like we don't add the '
                if (strOperatorValue.Contains("LIKE"))
                    valueQueue.Enqueue(string.Format(strOperatorValue, fieldName, value));
                else
                    valueQueue.Enqueue(string.Format(strOperatorValue, fieldName, "'" + value + "'"));
            }

            isSuccess = true;
        }
        catch
        {
            isSuccess = false;
            throw;
        }

        return isSuccess;
    }

    private static string GetOperatorString(string tagName, out string operatorType)
    {
        string operatorString = string.Empty;

        switch (tagName)
        {
            case "Or":
                operatorString = "OR";
                operatorType = "statement";
                break;
            case "And":
                operatorString = "AND";
                operatorType = "statement";
                break;
            case "Eq":
                operatorString = "{0} = {1}";
                operatorType = "value";
                break;
            case "Neq":
                operatorString = "{0} != {1}";
                operatorType = "value";
                break;
            case "Gt":
                operatorString = "{0} > {1}";
                operatorType = "value";
                break;
            case "Lt":
                operatorString = "{0} < {1}";
                operatorType = "value";
                break;
            case "Geq":
                operatorString = "{0} >= {1}";
                operatorType = "value";
                break;
            case "Leq":
                operatorString = "{0} <= {1}";
                operatorType = "value";
                break;
            case "BeginsWith":
                operatorString = "{0} LIKE '{1}%'";
                operatorType = "value";
                break;
            case "Contains":
                operatorString = "{0} LIKE '%{1}%'";
                operatorType = "value";
                break;
            case "IsNotNull":
                operatorString = "{0} IS NOT NULL";
                operatorType = "is";
                break;
            case "IsNull":
                operatorString = "{0} IS NULL";
                operatorType = "is";
                break;

            default:
                operatorString = string.Empty;
                operatorType = string.Empty;
                break;
        }

        return operatorString;
    }
}

0

如果您使用某种ado.net连接器与SharePoint进行连接,则可以实现这一点,请查看http://www.bendsoft.com/net-sharepoint-connector/

它使您能够像操作普通的SQL表格一样访问SharePoint列表

例如,插入一些数据

public void SharePointConnectionExample1()
{
    using (SharePointConnection connection = new SharePointConnection(@"
                Server=mysharepointserver.com;
                Database=mysite/subsite
                User=spuser;
                Password=******;
                Authentication=Ntlm;
                TimeOut=10;
                StrictMode=True;
                RecursiveMode=RecursiveAll;
                DefaultLimit=1000;
                CacheTimeout=5"))
    {
        connection.Open();
        using (SharePointCommand command = new SharePointCommand("UPDATE `mytable` SET `mycolumn` = 'hello world'", connection))
        {
            command.ExecuteNonQuery();
        }
    }
}

或者将选择列表数据返回到一个 DataTable

string query = "SELECT * FROM list";
conn = new SharePointConnection(connectionString);
SharePointDataAdapter adapter = new SharePointDataAdapter(query, conn);

DataTable dt = new DataTable();
adapter.Fill(dt);

或者使用一个辅助方法来填充DataGrid

string query = "Select * from mylist.viewname";
DataGrid dataGrid = new DataGrid();
dataGrid.DataSource = Camelot.SharePointConnector.Data.Helper.ExecuteDataTable(query, connectionString);
dataGrid.DataBind();
Controls.Add(dataGrid);

这里有一个网络研讨会,演示了如何为SharePoint构建一个简单的查询浏览器,http://www.youtube.com/watch?v=HzKVTZEsL4Y

希望对您有所帮助!


谢谢Trikks。我认为这可能与我试图做的相反。由于SPLists中的数据不会被保留,因此我需要使用SPList视图的过滤器/排序/字段查询SQL Server DW。 - OzymandiasII

0

Microsoft通过以下两种方式支持SharePoint列表数据访问: 1. SharePoint对象模型-SPSite和SPWeb 2. 列表Web服务。访问路径为http://Your_Site/_vti_bin/lists.asmx

对SharePoint列表进行任何添加/更新/删除/选择操作,使用上述两种方法之一都会经过未经管理的COM组件。该COM负责与内容数据库建立连接;在表格上应用数据锁定并检索数据。该COM组件具有自己的逻辑/机制来在内容数据库表格上应用数据锁定,而Sharepoint开发人员无法控制数据锁定机制。如果直接在内容数据库表格上执行T-SQL语句(添加/更新/删除/选择),则此内置逻辑可能会中断,并导致未知结果或错误。Microsoft不支持在内容数据库表格上直接执行T-SQL语句。


0
我已经使用以下CAML检查了Francis发布的代码:
<Where>
    <Or>
        <And>
            <Neq><FieldRef Name="F1" /><Value Type="Text">Yes</Value></Neq>
            <Neq><FieldRef Name="F2" /><Value Type="Text">Yes</Value></Neq>
        </And>
        <Eq><FieldRef Name="F3" /><Value Type="Text">Yes</Value></Eq>
    </Or>
</Where>

但它不起作用... 在这种情况下,结果将是:F1<>'Yes' AND ( F2<>'Yes' OR F3='Yes' )。

我在以下方法中进行了一些修复:

private bool ProcessWhereNode(XmlNode xmlNode, ref StringBuilder sb) {
        bool isSuccess = false;
        Stack<string> operatorStack = new Stack<string>();
        Queue<string> valueQueue = new Queue<string>();
        string previousOp = string.Empty;
        string strOperator = string.Empty;

        try {
            //Call a method to iterate "recursively" throught the nodes to get the values and operators.
            if (ProcessRecursiveWhereNode(xmlNode, "", "", ref operatorStack, ref valueQueue)) {

                // For each operator adding parenthesis before starting 
                StringBuilder sbTmp = new StringBuilder();
                operatorStack.ToList().ForEach(x => sbTmp.Append("("));
                sb.Append(sbTmp.ToString());

                while (valueQueue.Count > 0) {
                    if (operatorStack.Count > 0) {
                        strOperator = operatorStack.Pop();

                    } else {
                        strOperator = string.Empty;
                    }

                    sb.Append(valueQueue.Dequeue());

                    // After each logical operation closing parenthesis 
                    if (previousOp != string.Empty)
                        sb.Append(")");

                    if (strOperator != string.Empty) 
                        sb.Append(" " + strOperator + " ");

                    previousOp = strOperator;
                }
            }
            isSuccess = true;
        } catch (Exception) {
            isSuccess = false;
        }

        return isSuccess;
    }

这将把括号内的内容分组...就是这样


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接