Sharepoint OLE DB - не можете вставить записи? Ошибка «Поле не обновляется» - PullRequest
2 голосов
/ 08 апреля 2010

Мне нужно написать простое приложение на C # .NET для извлечения, обновления и вставки некоторых данных в список Sharepoint.

Я НЕ разработчик Sharepoint, и у меня нет контроля над нашим сервером Sharepoint. Я бы предпочел не разрабатывать это в правильной среде разработки sharepoint просто потому, что я не хочу развертывать свое приложение на сервере Sharepoint - я бы предпочел просто обращаться к данным извне.

Во всяком случае, я обнаружил, что вы можете получить доступ к данным Sharepoint с помощью OLE DB, и я попытался успешно использовать некоторые 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.

Я немного погуглил и, очевидно, вы не можете вставить данные через OLE DB !

Кто-нибудь знает, есть ли возможные обходные пути?

Я мог бы попытаться использовать Sharepoint Web Services, но сначала попробовал, и у меня было очень много времени для аутентификации. Это мой единственный вариант?

Ответы [ 6 ]

2 голосов
/ 09 апреля 2010

Из-за лицензирования для SharePoint я бы не вставлял записи непосредственно в базу данных конечного пользователя! Во всяком случае, используйте собственные веб-службы Sharepoint, т. Е. http://server/site/_vti_bin/Lists.asmx

В SharePoint есть МНОГИЕ веб-службы, к которым можно обращаться практически для всего, что SharePoint делает изначально.

Каждое семейство сайтов может использовать свою собственную веб-службу, нет необходимости отправлять код на сервер, нет сборок, нет прямых изменений базы данных ... они довольно просты в использовании, и на них имеется множество статей как от Microsoft, так и от других. .

Вам необходимо присоединить нормальный класс NetworkCredentials с правильными данными пользователя и связать его с экземпляром класса Web-сервиса.

Если в вашем SharePoint используется SQL Server, вы можете попробовать использовать пространство имен SqlClient, а не OLEDB, и прелесть веб-служб заключается в том, что вам не нужно сильно беспокоиться о том, какая база данных контента находится в вашем семействе сайтов, особенно если SharePoint создает их на лету, а не администратор, фактически определяющий его.

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

Приветствие.

2 голосов
/ 08 апреля 2010

Поддержка OLEDB для меня очень важная новость, я думаю, потому что она обычно не используется из-за того, что она доступна только для чтения. Я обычно использую объектную модель на самом сервере. Это не слишком хлопотно - вам действительно нужно включить только одну ссылку, и это значительно проще, чем использование веб-сервисов. Если вы хотите работать извне, однако, веб-сервисы - ваш единственный выбор. Либо так, либо объедините два подхода и разработайте свой собственный веб-сервис, который работает на сервере под управлением IIS и содержит код объектной модели.

1 голос
/ 19 сентября 2012

Решение использовать OLEDB для записи в список SharePoint состоит в том, чтобы указать IMEX = 0 в строке подключения.

http://www.connectionstrings.com/sharepoint

1 голос
/ 26 июля 2011

То же самое верно, используя ADO и INSERT INTO операторы

Если вы ссылаетесь на список в Access, вы можете использовать его как собственную таблицу доступа.

Dim db as Database
Set db = CurrentDb
db.Execute "INSERT INTO [List Name]..."
0 голосов
/ 25 ноября 2011

Правда ли, что данные не обновляются через OLE DB? Я думаю, что статья, на которую вы ссылаетесь, конкретно относится к многозначным («сложным») типам данных , которые являются функцией механизма доступа к данным начиная с версии Access2007 (т.е. SharePoint использует базу данных Access). Взгляните на эту статью , в которой используется DAO (библиотека ACEDAO) для манипулирования многозначными данными.

0 голосов
/ 09 апреля 2010

Я также использую Олицетворение, если необходимо:

    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 (); будет работать с учетными данными этого пользователя.

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

Приветствие.

...