Как обновить список SharePoint Online, если в базу данных вставлена ​​новая запись? - PullRequest
0 голосов
/ 19 июня 2019

У меня есть база данных MySQL, в которой хранится личная информация. При приеме на работу нового сотрудника он / она заполняет некоторую личную информацию, и эти данные сохраняются в таблице.

После некоторых исследований (а так как у меня нет доступа к другим системам - только к базе данных), планируется создать консольное приложение C #, которое извлекает данные и сравнивает их со списком SharePoint. Я хочу обновить список (создать новый элемент), если в базе данных есть новая запись, которой ранее не было в списке SharePoint.

Обратите внимание, что если список SharePoint содержит больше столбцов, то таблица с дополнительной ручной информацией.

Я разместил код подключения к базе данных и способ получения данных.

Как я могу проверить, существует ли элемент в списке SharePoint? Кто-нибудь сможет дать ответ, включающий код для создания и вставки нового элемента? У меня есть два столбца (и в базе данных, и в списке SP), которые могут работать в качестве первичного ключа.

Существует REST API, который поддерживает CRUD, поэтому я думаю, что это должно быть просто.

Список SharePoint:
SharePoint list

using System;
using System.Windows;

public class DbConnection
{
    private String databaseName;
    private String serverAddress;
    private String pwd;
    private String userName;
    private Boolean connected;
    private MySql.Data.MySqlClient.MySqlConnection conn;

    public DbConnection(String databaseName, String serverAddress, String pwd, String userName)
    {
        this.databaseName = databaseName;
        this.serverAddress = serverAddress;
        this.pwd = pwd;
        this.userName = userName;
        connected = false;
    }

    public void Connect()
    {
        if (connected == true)
        {
            Console.Write("There is already a connection");
        }
        else
        {
            connected = false;
            String connectionString = "server=" + serverAddress + ";" + "database=" + databaseName + ";" + "uid=" + userName + ";" + "pwd=" + pwd + ";";
            Console.WriteLine(connectionString);

            try
            {
                conn = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
                conn.Open();
                Console.Write("Connection was succesfull");
            }
            catch (MySql.Data.MySqlClient.MySqlException ex)
            {
                 MessageBox.Show(ex.Message);
            }
        }
    }

    public Boolean IsConnected()
    {
        return connected;
    }

    public MySql.Data.MySqlClient.MySqlConnection getConnection()
    {
        return conn;
    }

    public void Close()
    {
        conn.Close();
        connected = false;
    }
}

Затем я получаю данные примерно так:

using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace daily_CC_SP_update
{
    class Program
    {
        static void Main()
        {
            DbConnection mySQLConn = new DbConnection(dbName, serverAddress, pwd, userName);
            mySQLConn.Connect();

            string sqlQuery = "SELECT * FROM tbl_CC_SP";
            MySqlCommand sqlCom = new MySqlCommand(sqlQuery, mySQLConn.getConnection());
            MySqlDataReader reader = sqlCom.ExecuteReader();

            Console.WriteLine("Following output from DB");
            if(reader.Read())
            {
                Console.WriteLine(reader.GetString(0));
            }

            //Keep the console alive until enter is pressed, for debugging
            Console.Read();
            mySQLConn.Close();

        }
    }
}

Я создам представление в базе данных для получения правильных данных.

Ответы [ 3 ]

1 голос
/ 19 июня 2019

Сначала просто уточнить :) .. Вы используете SharePoint on-prem, верно?Таким образом, мы можем использовать решения Farm.Если да, то я бы разрешил этот случай с помощью следующего решения.Я хотел бы разработать SPJob (задание таймера SharePoint).Он может быть включен только в решение Farm.В основном это выглядит так:

  1. создайте проект Farm в решении
  2. добавьте класс, который наследуется от SPJobDefinition, и поместите свою логику в метод Execute, который необходимо переопределить (в этом методе создайтестандартное соединение SQL и запросите эту таблицу из базы данных mySQL, затем сравните с вашим SPList и выполните работу :)) (также, возможно, здесь хорошим подходом было бы сохранить некоторые учетные данные для этой строки соединения в каком-то SPList на каком-либо сайте конфигурации или где-то еще)..не жестко его закодировать;)) Например,

public class CustomJob : SPJobDefinition
{
    public CustomJob() : base() { }
    public CustomJob(string jobName, SPService service) : base(jobName, service, null, SPJobLockType.None)
    {
        this.Title = jobName;
    }
    public CustomJob(string jobName, SPWebApplication webapp) : base(jobName, webapp, null, SPJobLockType.ContentDatabase)
    {
        this.Title = jobName;
    }
    public override void Execute(Guid targetInstanceId)
    {
        SPWebApplication webApp = this.Parent as SPWebApplication;
        try
        {
            // Your logic here
        }
        catch (Exception ex)
        {
            SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("CustomJob - Execute", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, ex.Message, ex.StackTrace);
        }
    }
}
добавьте новую функцию в решение, которое называется webApplication, и добавьте получатель событий к этой функции при активной функции зарегистрируйте задание таймера (не забудьте удалить его при деактивированной :))

public class Feature2EventReceiver : SPFeatureReceiver
{
    const string JobName = "CustomJob";
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        try
        {
            SPSecurity.RunWithElevatedPrivileges(delegate ()
            {
                // add job
                SPWebApplication parentWebApp = (SPWebApplication)properties.Feature.Parent;
                DeleteExistingJob(JobName, parentWebApp);
                CreateJob(parentWebApp);
            });
        }
        catch (Exception ex)
        {
            SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("CustomJob-FeatureActivated", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, ex.Message, ex.StackTrace);
        }
    }
    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        lock (this)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate ()
                {
                    // delete job
                    SPWebApplication parentWebApp = (SPWebApplication)properties.Feature.Parent;
                    DeleteExistingJob(JobName, parentWebApp);
                });
            }
            catch (Exception ex)
            {
                SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("CustomJob-FeatureDeactivating", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, ex.Message, ex.StackTrace);
            }
        }
    }
    private bool CreateJob(SPWebApplication site)
    {
        bool jobCreated = false;
        try
        {
            // schedule job for once a day
            CustomJob job = new CustomJob(JobName, site);
            SPDailySchedule schedule = new SPDailySchedule();
            schedule.BeginHour = 0;
            schedule.EndHour = 1;
            job.Schedule = schedule;

            job.Update();
        }
        catch (Exception)
        {
            return jobCreated;
        }
        return jobCreated;
    }
    public bool DeleteExistingJob(string jobName, SPWebApplication site)
    {
        bool jobDeleted = false;
        try
        {
            foreach (SPJobDefinition job in site.JobDefinitions)
            {
                if (job.Name == jobName)
                {
                    job.Delete();
                    jobDeleted = true;
                }
            }
        }
        catch (Exception)
        {
            return jobDeleted;
        }
        return jobDeleted;
    }
}

развертывание и активация вашей функции в веб-приложении (я думаю, что лучше всего настроить работу так, чтобы она выполнялась каждый день или каждый час)

  • хорошая статья с примером того, какдля этого все можно найти здесь (я знаю, что статья для SP 2010, но она будет работать так же для 2013, 2016 и, вероятно, также 2019 (с этой предварительной версией у меня не так многоexp):)
  • другая статья с таким же решением здесь (это для SP 2013)

** Обновление **

для SharePoint Online вышеупомянутое решение не будет работать, так как это решение для фермы.В Online решение как всегда что-то «внешнее» :).Наверняка у вас уже есть какой-то сервер, на котором вы храните решения для SP онлайн (например, приложения SP, размещенные у провайдера и т. Д.).Мой подход заключается в разработке простого консольного приложения на C #.Сначала в этом приложении выполните SQL-соединение с mySql и запросите таблицу, чтобы получить данные. Затем выполните CSOM-запрос SharePoint List, чтобы выполнить сравнение.что-то вроде этого



    using (var clientContext = new ClientContext("url"))
    {
        CamlQuery camlQuery = new CamlQuery();
        string query = "add some query here";
        camlQuery.ViewXml = query;
        collListItem = list.GetItems(camlQuery);
        clientContext.Load(collListItem, items => items.Include( item => item["Title"], item => .... // add other columns You need here);
        clientContext.ExecuteQuery();

        if (collListItem.Count > 0)
        {
            // Your code here :)
        }
    } 

Также имейте в виду, что вы можете запустить CSOM с учетными данными другого пользователя (например, администратором), указав сетевые учетные данные следующим образом:


NetworkCredential _myCredentials = new NetworkCredential("user", "password", "companydomain");

Также, пожалуйста,знать о пороге ... в CSOM Вы всегда можете использовать разбитый на страницы запрос, если сначала вы получили 5000 элементов, затем до 5000 и т. д. до тех пор, пока коллекция не станет пустой :).После того, как вы вручную запустите это консольное приложение, чтобы убедиться, что оно работает правильно, просто добавьте это консольное приложение в планировщик задач на этом сервере в качестве новой задачи в библиотеке задач.Также там Вы можете указать время запуска, например, запускать каждый час или день и т. Д. здесь - хорошая статья о переполнении стека, как добавить такую ​​задачу

.. Надеюсь, теперь ответ лучшедля вашей среды:)

0 голосов
/ 12 июля 2019

Решение состоит в том, чтобы установить элементы ["LockUpColumn"] не в строку, а в поле блокировки

0 голосов
/ 27 июня 2019

Так что у меня был большой прогресс в моей программе на c #.У меня есть полнофункциональное соединение между базой данных MySql и SharePoint через Интернет с использованием MySql.Data CSOM.Может манипулировать и контролировать все списки и данные внутри.

Однако у меня есть одна проблема, но я не уверен, что это можно решить.Немного информации, которую я мог найти вокруг этой темы.

Я создаю новый ListItem.Установите для всех полей значение.Но есть один столбец типа «Персона».У каждого сотрудника есть свой сайт, на который он ссылается, например, Lookup.При добавлении значения в это поле сервер выдает мне следующую ошибку:

Microsoft.SharePoint.Client.ServerException: Invalid data has been used to update the list item. The field you are trying to update may be read only.
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream)
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponse()
   at Microsoft.SharePoint.Client.ClientRequest.ExecuteQueryToServer(ChunkStringBuilder sb)
   at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()
   at SPList.CreateNewItem(String userName, Int32 employeeNumber, String fullName, String firstName, String lastName, DateTime emplymentStart, DateTime employmentEnd, String department, String mobile, String address, String postcode, String postTown, String email) in C:\Users\fjs\source\repos\daily_CC_SP_update\SPList.cs:line 153

Спецификация поля SharePoint

Вот код, в котором я создаю новый элемент.

using System;
using Microsoft.SharePoint.Client;
using System.Linq;
using System.Net;

public class SPList
{
    private readonly ClientContext context;
    private readonly List list;
    private readonly ListItemCollection items;
    private readonly Web web;

    //Credentials may be needed, its commented out!
    public SPList(String siteUrl, String listName, NetworkCredential netCred)
    {
        try
        {
            //NetworkCredential _myCredentials = netCred;
            context = new ClientContext(siteUrl);
            list = context.Web.Lists.GetByTitle(listName);
            items = list.GetItems(CamlQuery.CreateAllItemsQuery());
            web = context.Web;
            context.Load(items);
            context.Load(list);
            context.Load(context.Web.Lists, lists => lists.Include(list => list.Title));
            context.ExecuteQuery();
            Console.WriteLine("Connected to SharePoint successfully!");
        }
        catch(Exception e)
        {
            Console.WriteLine(e);
        }
    }

    public void CreateNewItem(String userName, int employeeNumber, String fullName, String firstName, String lastName, DateTime emplymentStart, DateTime employmentEnd, String department, String mobile, String address, String postcode, String postTown, String email)
    {
        try
        {
            ListItemCreationInformation newItemSepc = new ListItemCreationInformation();
            ListItem newItem = list.AddItem(newItemSepc);
            newItem["Title"] = userName;
            newItem["Employee_x0020_Number"] = employeeNumber;
            newItem["Full_x0020_Name"] = fullName;
            newItem["First_x0020_Name"] = firstName;
            newItem["Last_x0020_Name"] = lastName;
            newItem["_x000a_Employment_x0020_start_x0"] = emplymentStart.Date;
            newItem["Employment_x0020_end_x0020_date"] = employmentEnd.Date;
            newItem["Department"] = department;
            newItem["Mobile"] = mobile;
            newItem["Adress"] = address;
            newItem["Postcode"] = postcode;
            newItem["Post_x0020_town"] = postTown;
            newItem["Email"] = email;
            newItem["Person"] = fullName;
            newItem.Update();
            context.ExecuteQuery();
        }
        catch(Exception e)
        {
            Console.WriteLine(e);
        }
    }
}

Если я прокомментирую newItem ["Person"] = fullName;Код работает нормально. Можно ли это как-то исправить?В противном случае мне нужно отредактировать элемент в SharePoint и добавить значение: /

Странные имена полей, потому что SharePoint по какой-то причине хранит его таким образом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...