Sharepoint OLE DB - 无法插入记录? “字段不可更新”错误

时间:2010-04-08 19:08:16

标签: c# sql sharepoint ado.net oledb

我需要编写一个简单的C#.NET应用程序来检索,更新和插入Sharepoint列表中的一些数据。

我不是Sharepoint开发人员,而且我无法控制我们的Sharepoint服务器。我宁愿不必在proper sharepoint development environment中开发它只是因为我不想在Sharepoint服务器上部署我的应用程序 - 我宁愿只是从外部访问数据。

无论如何,我发现你可以使用OLE DB访问Sharepoint数据,我尝试使用一些ADO.NET成功:

var db = DatabaseFactory.CreateDatabase();
DataSet ds = new DataSet();
using (var command = db.GetSqlStringCommand("SELECT * FROM List"))
{
    db.LoadDataSet(command, ds, "List");
}

以上作品。

但是,当我尝试插入时:

using (var command = db.GetSqlStringCommand("INSERT INTO List ([HeaderName],
    [Description], [Number]) VALUES ('Blah', 'Blah', 100)"))
{
    db.ExecuteNonQuery(command);
}

我收到此错误:

Cannot update 'HeaderName'; field not updateable.

我做了一些谷歌搜索,显然是you cannot insert data through OLE DB

有没有人知道是否有可能的解决方法?

我可以尝试使用Sharepoint Web Services,但是我最初尝试过这种方式并且正在进行身份验证。这是我唯一的选择吗?

6 个答案:

答案 0 :(得分:2)

OLEDB支持对我来说是一个非常新闻,我想因为它是只读的性质而不常用。我倾向于使用服务器本身的对象模型。这不是太麻烦 - 您只需要包含一个引用,并且使用Web服务要容易得多。如果您想从外部运行,但Web服务是您唯一的选择。要么是合并这两种方法,要么开发自己的Web服务,这些服务在IIS下的服务器上运行,并包含对象模型代码。

答案 1 :(得分:2)

由于SharePoint的许可,我不会将记录直接插入后端数据库!无论如何,使用本机Sharepoint Web服务,即http://server/site/_vti_bin/Lists.asmx

SharePoint拥有许多Web服务,您可以调用它来执行SharePoint本身所做的几乎任何事情。

每个网站集都可以使用他们自己的Web服务,不需要在服务器上运行代码,没有程序集,没有直接的数据库更改......它们非常易于使用,并且有很多文章都来自Microsoft和其他人

您需要附加一个具有正确用户详细信息的普通NetworkCredentials类,并将其绑定到实例化的Web Service类。

如果您的SharePoint使用SQL Server,您可以尝试使用SqlClient命名空间而不是OLEDB,那么Web服务的优点是您不必担心网站集所使用的内容数据库,尤其是SharePoint即时创建它们而不是管理员实际指定它。

希望这有助于。

干杯。

答案 2 :(得分:1)

使用ADOINSERT INTO语句

也是如此

如果链接到Access中的列表,则可以将其用作本机访问表。

Dim db as Database
Set db = CurrentDb
db.Execute "INSERT INTO [List Name]..."

答案 3 :(得分:1)

将OLED 用于写入 到SharePoint列表的解决方案是在连接字符串中指定IMEX = 0.

http://www.connectionstrings.com/sharepoint

答案 4 :(得分:0)

如果需要,我也会使用模拟:

    using System.Security.Principal;

使用System.Runtime.InteropServices;

 #region Constants
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;
 #endregion

public WindowsImpersonationContext impersonationContext;

#region Win32 API
    [DllImport("advapi32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    public static extern int LogonUserA(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern int DuplicateToken(IntPtr ExistingTokenHandle, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern bool RevertToSelf();
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern long CloseHandle(IntPtr handle);
    #endregion

public bool Impersonate(string userName, string domain, string password)
    {
        try
        {
            bool functionReturnValue = false;
            WindowsIdentity tempWindowsIdentity = default(WindowsIdentity);
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;
            functionReturnValue = false;
            if (RevertToSelf())
            {
                if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if ((impersonationContext != null))
                        {
                            functionReturnValue = true;
                        }
                    }
                }
            }
            if (!tokenDuplicate.Equals(IntPtr.Zero))
            {
                CloseHandle(tokenDuplicate);
            }
            if (!token.Equals(IntPtr.Zero))
            {
                CloseHandle(token);
            }

            return functionReturnValue;
        }
        catch (Exception ex)
        {
            SQMSLog.WriteLogEntry(ex.Message, "SYSTEM");
            return false;
        }
    }

public void UndoImpersonate()
    {
        impersonationContext.Undo();
    }

首先调用模拟函数:

  //Add Miscellaneous Data Details
            data.ListNameEx = Settings.Default.SPListLoader_List_Name;
            //Instantiate the Web Service
            SPListService.Lists lists = new SPListLoaderService.SPListService.Lists();
            //Bind Appropriate Credentials to the Web Service
            lists.Credentials = new NetworkCredential(data.UserName, data.Password, data.Domain);
            //Set the List Object URI
            lists.Url = data.URI.TrimEnd('/') + "/_vti_bin/lists.asmx";

完成后,您需要发布上下文:

UndoImpersonate();

以上是非常重要的,一旦你调用了Impersonate()就执行了什么;将在该用户凭据下运行。

希望这有助于。

干杯。

答案 5 :(得分:0)

是否可以通过OLE DB更新数据?我认为您链接到的文章特指multi-valued ("complex") data types,它是Access2007版本之后的Access数据引擎的一个功能(即SharePoint使用Access数据库)。看一下this article,它使用DAO(ACEDAO库)来操作多值数据。