SharePoint CAML-запрос к T-SQL - PullRequest
       36

SharePoint CAML-запрос к T-SQL

2 голосов
/ 29 апреля 2011

Я надеялся преобразовать запрос CAML в T-SQL. Для моего сайта SharePoint у меня также есть хранилище данных (SQL Server 2005), в котором хранятся те же данные (оно заполняется через SPList EventReceivers: ItemAdded, ItemUpdated).

Я участвую в задаче по управлению ростом списков и скоростью пользовательских веб-частей, отображающих данные списков. Вместо этого я надеюсь отобразить содержимое нашего списка с помощью хранилища данных, а затем мы собираемся удалить элементы из списков SPL, в которых рабочий процесс завершен.

В настоящее время пользователь настраиваемой веб-части, которая отображает содержимое SPList, может выбирать 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>

до

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 голосов
/ 29 июля 2013

Я также надеялся найти фрагмент кода для преобразования CAML в SQL, чтобы создать собственный оператор SQL для доступа к данным.

Мой основной проект заключается в создании расширения ленты SharePoint для экспорта содержимого списков (внутреннего и внешнего) в CSV, а в случае внешних списков, чтобы иметь возможность обойти ограничение регулирования (2000), установленное для внешних типов содержимого (BCS) ).

Я использую информацию в хранилище метаданных и безопасном хранилище для построения строки подключения и прямого доступа к базе данных.

Когда мне нужно было усовершенствовать мой код, включив в него фильтры, я закончил тем, что собрал свои собственные методы, чтобы получить часть «Где» в представлении запроса и преобразовать ее в 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%'"

Вот методы:

Этот метод извлекает узел «Где» из представления Query и передайте его методу для обработки и верните 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;
    }

Этот метод вызовет другой метод для рекурсивного обхода всех узлов, чтобы получить значения и операторы в узле View Query «Where». Он будет заключать в круглые скобки операторы «ИЛИ», чтобы сохранить приоритет операции.

    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 голос
/ 13 сентября 2011

Мой очень простой класс для преобразования из строки 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>

Класс Src:

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

(боб.)

1 голос
/ 29 апреля 2011

Технически это не ответ, но я чувствую, что это необходимо.Ваш подход немного отсталый.Мне кажется, что вы действительно пытаетесь сделать это использовать sharepoint в качестве интерфейса вашего хранилища данных.Если это так, я бы переключил ваш подход на один из нескольких вариантов, выходящих за рамки этого вопроса.

Доступ к данным в sharepoint поддерживается только Microsoft через объектную модель, веб-сервисы или пользовательский интерфейс.Любое взаимодействие за пределами этого может привести к широкому спектру неподдерживаемых режимов, от поврежденных данных, блокировок данных, различных наборов результатов, доступа к безопасности и т. Д.Это позволило бы вам использовать хранилище данных для центрального хранилища, а также предоставить вам встроенную функциональность sharepoint взаимодействий в списке.

Я не уверен, какую версию вы используете, но если вы ДЕЙСТВИТЕЛЬНО хотите получить доступ к данным напрямую, в сообществе SQL имеется большое количество статей о прямом доступе к данным.Существует также проект codeplex для LINQtoSharePoint http://linqtosharepoint.codeplex.com/. Вы можете использовать это для поддержки объектов, что вы можете использовать LINQ, чтобы предоставить вам функциональность типа sql-esque.

0 голосов
/ 19 июля 2016

спасибо за вашу помощь, мне это тоже нужно, ваш код был хорош, но я немного его улучшил:

  • оператор нулевой и не является ручкой
  • немногоошибка при экранировании с помощью оператора like

будьте осторожны, код не экранирует имя столбца (вы должны сделать это в зависимости от вашего движка базы данных)

вот код встатический класс:

///5586533/sharepoint-caml-zapros-k-t-sql
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 голосов
/ 11 сентября 2015

Я проверил код, опубликованный Фрэнсисом, со следующим CAML:

<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 <> 'Да'И (F2 <> 'Да' ИЛИ ​​F3 = 'Да').

Я сделал некоторые исправления в следующем методе:

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

Это сгруппирует пару в скобках ..и это все

0 голосов
/ 10 мая 2011

Microsoft поддерживает доступ к данным списка SharePoint через: 1. Объектная модель SharePoint - SPSite и SPWeb 2. Списки веб-сервиса. Путь к доступу http://Your_Site/_vti_bin/lists.asmx

Любые операции добавления / обновления / удаления / выбора в списке SharePoint выполняются с помощью любого из двух вышеуказанных методов, проходящих через неуправляемый компонент COM. Этот COM отвечает за установление соединения с Content DB; применение блокировок данных к таблицам и извлечение данных. Этот COM-компонент имеет собственную логику / механизм для применения блокировки данных к таблицам базы данных, а разработчик Sharepoint не имеет контроля над механизмом блокировки данных. Если операторы T-SQL (Add / Update / Delete / Select) выполняются непосредственно в таблицах Content DB, эта логика In-Build может сломаться и привести к неизвестным результатам или ошибкам. Microsoft не поддерживает прямое выполнение операторов T-SQL для таблиц БД содержимого.

0 голосов
/ 29 апреля 2011

Это возможно, если вы используете какой-то коннектор ado.net для SharePoint, взгляните на http://www.bendsoft.com/net-sharepoint-connector/

Это позволяет вам общаться со списками SharePoint, как если бы они были обычными таблицами SQL

Например, для вставки некоторых данных

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

Надеюсь, это поможет!

...