c# - 如果数据库中插入新记录,如何更新 SharePoint Online 列表?

标签 c# mysql rest sharepoint-online sharepoint-designer

我有一个保存个人信息的 MySQL 数据库。每当新员工被雇用时,他/她都会填写一些个人信息,并将这些数据存储在表中。

经过一些研究(并且由于我无法访问其他系统 - 只能访问数据库),计划是构建一个 C# 控制台应用程序来检索数据并根据 SharePoint 列表进行检查。如果数据库中的新记录以前不存在于 SharePoint 列表中,我想更新列表(创建新项目)。

请注意,如果 SharePoint 列表包含更多列,则表格中包含其他手动信息。

我已经发布了针对数据库的连接代码以及如何检索数据。

如何检查该项目是否存在于 SharePoint 列表中?有人能够提供包含用于创建和插入新项目的代码的答案吗? 我有两列(在数据库和 SP 列表中)可以用作主键。

有一个支持 CRUD 的 REST API,所以我想这应该是理所当然的。

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();

        }
    }
}

我将在数据库中创建一个 View 来检索正确的数据。

最佳答案

首先要澄清一下:)..您使用的是本地 SharePoint,对吗?所以我们可以使用 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;
        }
    }
    
  • 在网络应用上部署并激活您的功能(我认为最好是将作业配置为每天或每小时运行)

    • 一篇不错的文章,其中包含一些如何做到这一点的示例,所有这些都可以找到 here (我知道这篇文章是针对 SP 2010 的,但它对于 2013 年、2016 年甚至 2019 年也同样适用(对于这个本地版本,我没有太多经验):)
    • 另一篇具有相同解决方案的文章 here (这是 SP 2013 的)
  • ** 更新 **

    对于 SharePoint Online,上述解决方案将不起作用,因为它是场解决方案。在在线中,解决方案始终是“外部”的:)。 当然,您已经拥有某种服务器,可以在线存储 SP 解决方案(例如提供商托管的 SP 应用程序等)。 我的方法是开发一个简单的 C# 控制台应用程序。首先在此应用程序中执行与 mySql 的 SQL 连接并查询表以获取数据..然后使用 CSOM 查询 SharePoint 列表进行比较。 像这样的东西

    
    
        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 个项目,等等,直到集合为空:)。 手动运行此控制台应用程序几次以确保其正常工作后,只需将此控制台应用程序添加到此服务器上的任务计划程序作为任务库中的新任务即可。此外,您还可以提供触发时间,例如每小时或每天运行一次等。here是一个很好的堆栈溢出帖子,介绍了如何添加此类任务

    ..我希望现在的答案更适合您的环境:)

    关于c# - 如果数据库中插入新记录,如何更新 SharePoint Online 列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56667790/

    相关文章:

    c# - 使用 linq 到 nhibernate 时未实现方法或操作

    mysql - 如果表中某个字段的特定值不存在,如何插入记录(sql查询)?

    IE 上的 AJAX POST 请求失败,错误为 "No Transport"?

    c# - OrderBy a List<Tuple<int, int>> 仅按 Item2

    C# Formatting DateTime 给我错误的结果

    PHP Login 登录后不会重定向

    php - PHP 中 Big5 转换为 UTF-8

    javascript - 如何向 AWS Amplify Express 服务器添加额外终端节点?

    ios - 移动应用程序的 REST API 请求

    c# - 如何以编程方式将按钮上的可见性绑定(bind)到 C# 中的 INotifyPropertyChanged bool 属性?