Freigeben über


Gewusst wie: Schreiben in Inhaltsdatenbanken mithilfe von LINQ to SharePoint

Letzte Änderung: Freitag, 24. Juni 2011

Gilt für: SharePoint Foundation 2010

Inhalt dieses Artikels
Schritt 1 und 2: Rufen Sie Verweise auf Websites und Listen ab
Schritt 3: Stellen Sie sicher, dass die Objektänderungsverfolgung aktiviert ist
Schritt 4: Fügen Sie grundlegenden Code für das Hinzufügen, Löschen, Recyceln oder Aktualisieren eines Listenelements hinzu
Schritt 5: Fügen Sie Infrastruktur zur Behandlung von Parallelitätskonflikten hinzu

In diesem Thema wird erklärt, wie Sie Code für den LINQ to SharePoint-Anbieter schreiben, um Listenelemente in Microsoft SharePoint Foundation-Listen hinzuzufügen oder zu entfernen und Werte von bestimmten Feldern in Listenelementen zu ändern.

Schritt 1 und 2: Rufen Sie Verweise auf Websites und Listen ab

Eine Anleitung zum Abrufen eines Verweises auf die Website und die Liste, deren Daten Sie ändern möchten, finden Sie in Schritt 1 und 2 des Themas Gewusst wie: Ausführen von Abfragen mithilfe von LINQ to SharePoint.

Schritt 3: Stellen Sie sicher, dass die Objektänderungsverfolgung aktiviert ist

Die ObjectTrackingEnabled-Eigenschaft muss den Standardwert true haben, damit Sie LINQ to SharePoint nutzen können, um Änderungen an der Datenbank vorzunehmen. Wenn Ihr Code diese Eigenschaft auf false setzt und das DataContext-Objekt mit diesem Wert abgefragt hat, kann die Eigenschaft nicht auf true zurückgesetzt werden. Entsprechend haben Sie, wenn Ihr Code das DataContext-Objekt abfragt und dann Änderungen an der Inhaltsdatenbank vornimmt, die folgenden zwei Optionen:

  • Sie sehen davon ab, dass Ihr Code die ObjectTrackingEnabled-Eigenschaft auf false setzt.

  • Sie erstellen ein neues DataContext-Objekt für die gleiche Website im Code und fügen es nach den Abfragen ein, jedoch bevor der Code in die Datenbank schreibt. Behalten Sie für die ObjectTrackingEnabled-Eigenschaft des neuen DataContext-Objekts den Standardwert true bei, und verwenden Sie das neue Objekt zum Schreiben in die Inhaltsdatenbank.

Schritt 4: Fügen Sie grundlegenden Code für das Hinzufügen, Löschen, Recyceln oder Aktualisieren eines Listenelements hinzu

Der grundlegende Code für das Schreiben in die Inhaltsdatenbanken ist einfach. Sie beginnen, indem Sie einen Verweis auf die Website und die Liste erstellen, und Sie schließen den Schritt mit einem Aufruf von SubmitChanges(). Dazwischen befindet sich der Code, in dem Sie mithilfe einer der *OnSubmit-Methoden der EntitySet<TEntity>-Klasse die gewünschten Änderungen vornehmen oder mithilfe von gewöhnlicher Syntax für Eigenschafteneinstellungen in Listenfelder schreiben. In allen folgenden Beispielen ist teamSite ein DataContext-Objekt, das eine Website darstellt, und TeamMembers ein EntitySet<TEntity>-Objekt, das eine Liste von Teammitgliedern darstellt.

Wichtiger HinweisWichtig

Das Objekt für das Listenelement, das Sie hinzufügen, löschen, recyceln oder aktualisieren, muss die EntityState-, die Id- und die Version-Eigenschaft haben. Dies ist der Fall, wenn die Klasse, die den Inhaltstyp darstellt, von SPMetal generiert wird. Die verschiedenen *OnSubmit-Methoden ordnen der EntityState-Eigenschaft Werte zu. Die Id- und die Version-Eigenschaft werden von der SharePoint Foundation-Laufzeit festgelegt. Ihr Code sollte in keine dieser drei Eigenschaften schreiben.

Hinzufügen eines Listenelements

Zum Hinzufügen eines Elements zu einer Liste erstellen Sie ein Objekt mit dem Inhaltstyp der Liste und übergeben es an die InsertOnSubmit(TEntity)-Methode.

Wichtiger HinweisWichtig

Alle Eigenschaften in dem Listenelementobjekt, die erforderliche Felder des Inhaltstyps darstellen, müssen einen Wert haben, bevor das Element in die Liste eingefügt wird. (Diese Eigenschaften werden mit einer [ColumnAttribute]-Dekoration deklariert, deren Required-Eigenschaft vorhanden und auf true festgelegt ist.) Beispielsweise erben alle Inhaltstypen vom grundlegenden Item-Inhaltstyp von SharePoint Foundation, und dieser Inhaltstyp hat ein erforderliches Title-Feld. Sie können solchen Eigenschaften zwischen dem Aufruf von InsertOnSubmit(TEntity) und dem Aufruf von SubmitChanges() Werte zuordnen. Es hat sich jedoch bewährt, erforderliche Eigenschaften so früh wie möglich zu initialisieren. Wenn kein Klassenkonstruktor vorhanden ist, der alle erforderlichen Eigenschaften initialisiert, können Sie einen Objektinitialisierer verwenden, wie im nachstehenden Beispiel gezeigt.

Im folgenden Beispiel wird gezeigt, wie Sie einer Liste ein Element hinzufügen und die Änderungen anschließend in der Datenbank speichern.

// Create the new list item.
TeamMember bob = new TeamMember() { Title="Bob Smith" };

// Set the item to be inserted.
teamSite.TeamMembers.InsertOnSubmit(bob);

// Write changes to the content database.
teamSite.SubmitChanges();

Es gibt auch eine InsertAllOnSubmit(IEnumerable<TEntity>)-Methode, die Sie zum Einfügen von mehreren Elementen verwenden können.

Löschen und Recyceln eines Listenelements

Im folgenden Beispiel wird gezeigt, wie Sie mithilfe der DeleteOnSubmit(TEntity)-Methode ein Element aus einer Liste entfernen können.

// Set the item to be deleted.
foreach (TeamMember teamMember in teamSite.TeamMembers)
{
    if (teamMember.Title = "Bob Smith")
    {
        teamSite.TeamMembers.DeleteOnSubmit(teamMember);
    }
}

// Write changes to the content database.
teamSite.SubmitChanges();

Wenn Sie ein Element nicht endgültig löschen, sondern vielmehr in den Papierkorb des Benutzers verschieben (recyceln) möchten, verwenden Sie die RecycleOnSubmit(TEntity)-Methode. Mithilfe der DeleteAllOnSubmit(IEnumerable<TEntity>)- und der RecycleAllOnSubmit(IEnumerable<TEntity>)-Methode können Sie außerdem mehrere Elemente auf einmal entfernen.

Ändern eines Felds in einem Listenelement

Zum Ändern des Werts eines Felds in einem Listenelement schreiben Sie einfach in die Eigenschaft, die das Feld darstellt, wie im folgenden Beispiel gezeigt:

// Set the property to a new value.
foreach (TeamMember teamMember in teamSite.TeamMembers)
{
    teamMember.TopTask = "Fiscal Planning";
}

// Write changes to the content database.
teamSite.SubmitChanges();

Mehrere Änderungen mit einem einzigen Aufruf von "SubmitChanges"

Mit einem Aufruf der SubmitChanges()-Methode kann der Code eine unbegrenzte Anzahl von Änderungen durchführen. Die beste Leistung wird erzielt, wenn der Code möglichst wenige Aufrufe dieser Methode ausführt. Im folgenden Codebeispiel wird gezeigt, wie mit einem einzigen Aufruf der SubmitChanges()-Methode mehrere Arten von Änderungen in die Inhaltsdatenbank geschrieben werden können:

// ‘sally’ is a TeamMember object.
teamSite.TeamMembers.RecycleOnSubmit(sally);

// ‘leftCompany’ is an IList of TeamMember objects
teamSite.TeamMembers.DeleteAllOnSubmit(leftCompany);

foreach (TeamMember teamMember in teamSite.TeamMembers)
{
    teamMember.TopTask = "Fiscal Planning";
}

// Write changes to the content database.
teamSite.SubmitChanges();

Die Änderungen, die übermittelt werden, müssen nicht alle die gleiche Liste betreffen. Änderungen an einzelnen oder allen Listen in einer Website können mit einem einzigen Aufruf der SubmitChanges()-Methode übermittelt werden.

Schritt 5: Fügen Sie Infrastruktur zur Behandlung von Parallelitätskonflikten hinzu

Wenn Sie Feldwerte geändert haben, überprüft das System für die Objektänderungsverfolgung vor dem Commit der Änderungen in der Inhaltsdatenbank durch einen Aufruf der SubmitChanges()-Methode, ob ein anderer Benutzer eines oder mehrere der betroffenen Listenelemente geändert hat, nachdem der aktuelle Benutzerprozess sie aus der Datenbank abgerufen hat. (Weitere Informationen zu diesem System finden Sie unter Nachverfolgen von Objektänderungen und vollständige Parallelität.) Besteht ein Parallelitätskonflikt, löst SubmitChanges() eine ChangeConflictException-Ausnahme aus. Zudem wird ein MemberChangeConflict-Objekt generiert, das Informationen über die Abweichung darstellt. Falls weitere Abweichungen zwischen dem aktuellen Clientwert für ein Feld und dem Wert des Felds in der Datenbank bestehen, werden auch diese jeweils durch ein MemberChangeConflict-Objekt dargestellt. Alle Abweichungen für ein gegebenes Listenelement werden der MemberConflicts-Eigenschaft eines ObjectChangeConflict-Objekts hinzugefügt. Je nachdem, welche Überladung von SubmitChanges() aufgerufen wurde und welche Parameter an diese übergeben wurden, können mehrere ObjectChangeConflict-Objekte vorhanden sein. Sie werden alle der ChangeConflicts-Eigenschaft des DataContext-Objekts hinzugefügt.

Der Code muss die Ausnahme abfangen und alle Abweichungen auflösen, bevor SubmitChanges() erneut aufgerufen wird. In manchen Situationen empfiehlt es sich, den Benutzer mit einer entsprechenden Aufforderung entscheiden zu lassen, wie die einzelnen Abweichungen aufgelöst werden sollen. Sie können die Benutzeroberfläche, die Sie dem Benutzer präsentieren, mit Daten aus den ObjectChangeConflict-Objekten in der ChangeConflicts-Eigenschaft und aus deren untergeordneten MemberChangeConflict-Objekten auffüllen, insbesondere der OriginalValue-, der DatabaseValue- und der CurrentValue-Eigenschaft.

TippTipp

Es ist ratsam, in der Benutzeroberfläche klar zwischen Abweichungen zu unterscheiden, die tatsächliche Parallelitätskonflikte darstellen – Abweichungen zwischen der OriginalValue- und der DatabaseValue-Eigenschaft –, und Abweichungen, die einfach nur Änderungen darstellen, die automatisch in die Inhaltsdatenbank geschrieben worden wären, wenn keine Parallelitätskonflikte aufgetreten wären, d. h. Abweichungen zwischen DatabaseValue und CurrentValue, wenn OriginalValue = DatabaseValue.

Implementieren Sie die Wahlmöglichkeiten des Benutzers mit Aufrufen einer Kombination aus folgenden Methoden:

In anderen Fällen erkennen Sie wahrscheinlich während des Codierens, auf welche Weise Abweichungen am besten aufgelöst werden. Hierbei spielen der Zweck der Anwendung und die Art der Änderungen, die sie an den Inhaltsdatenbanken vornimmt, eine Rolle. Es kann sich z. B. erweisen, dass Sie am besten eine Kombination aus den Methoden in der oben stehenden Liste aufrufen, ohne den Benutzer zu einer Eingabe aufzufordern. Vier wichtige Punkte müssen Sie bedenken, während Sie die Logik für die Auflösung von Abweichungen entwerfen:

  • Welche Version des Werts eines Felds soll in der Inhaltsdatenbank beibehalten werden: der ursprüngliche Wert, der aktuell in der Datenbank befindliche Wert, der Wert im Prozess der Anwendung (der Clientwert) oder ein vierter Wert? Orientierungshilfen finden Sie unter RefreshMode und in den Referenzthemen zu den Methoden in der obigen Liste. In den Artikeln in der folgenden Tabelle wird zwar der LINQ to SQL-Anbieter behandelt, doch gilt die darin beschriebene Logik auch für LINQ to SharePoint.

    Gewusst wie: Lösen von Parallelitätskonflikten durch das Zusammenführen mit Datenbankwerten (LINQ to SQL)

    Gewusst wie: Beheben von Parallelitätskonflikten durch das Erhalten von Datenbankwerten (LINQ to SQL)

    Gewusst wie: Beheben von Parallelitätskonflikten durch das Überschreiben von Datenbankwerten (LINQ to SQL)

  • Was soll geschehen, wenn der aktuelle Benutzer eine Änderung an einem Listenelement übermittelt hat, das ein anderer Benutzer ganz aus der Liste gelöscht hat? Weitere Informationen über die entsprechenden Optionen finden Sie unter Resolve(RefreshMode, Boolean) und ResolveAll(RefreshMode, Boolean).

  • Auf welcher Ebene müssen Ihre Entscheidungen über die zwei vorhergehenden Szenarien angewendet werden? Angenommen, Sie möchten die folgenden Regeln auf jede Abweichung für jedes Listenelement für jede Liste anwenden:

    • Listenelemente, die von einem anderen Benutzer gelöscht wurden, ignorieren.

    • Alle Änderungen, die vom Prozess Ihrer Anwendung vorgenommen wurden, sowie Änderungen durch andere Benutzerprozesse beibehalten, wobei Ihre Änderungen den Vorrang haben, wenn sie mit den Änderungen eines anderen Benutzers in Konflikt stehen.

    Die entsprechende Logik können Sie mit einem einfachen Aufruf der ChangeConflictCollection.ResolveAll()-Methode anwenden.

    Wenn jedoch alle Änderungen an den Elementen bestimmter Listen beibehalten werden müssen, während die Änderungen, die Ihr eigener Prozess an Elementen bestimmter anderer Listen vorgenommen hat, verworfen werden sollen, muss der Code die Member der ChangeConflicts-Eigenschaft durchlaufen, wobei unterschiedliche Überladungen von ObjectChangeConflict.Resolve() aufgerufen und unterschiedliche Parameter für unterschiedliche ObjectChangeConflict-Elemente übergeben werden.

    Für bestimmte Inhaltstypen müssen Sie möglicherweise unterschiedliche Regeln für unterschiedliche Felder anwenden. In diesem Fall muss der Code die Member der MemberConflicts-Eigenschaft bestimmter ObjectChangeConflict-Objekte durchlaufen, unterschiedliche Überladungen von MemberChangeConflict.Resolve() aufrufen und unterschiedliche Parameter für unterschiedliche Felder übergeben.

  • Wann soll eine ChangeConflictException-Ausnahme ausgelöst und wann sollen keine weiteren Änderungen mehr vorgenommen werden? Dies ist Teil der Logik für die Auflösung, obwohl Sie Ihre Entscheidung mit dem Aufruf von SubmitChanges() implementieren. Sie haben zwei Optionen: Sie können die Ausnahme sofort auslösen lassen, wenn ein Parallelitätskonflikt erkannt wird, oder Sie können festlegen, dass alle ausstehenden Änderungen noch geschrieben werden. Im letzteren Fall wird die Ausnahme ausgelöst (und die Änderungen an Feldern, für die ein Konflikt besteht, werden verworfen), wenn ein oder mehrere Parallelitätskonflikte erkannt werden. Ein Vorteil der zweiten Option liegt darin, dass die MemberConflicts-Eigenschaft eine vollständige Einzelauflistung aller Parallelitätskonflikte (und anderer Abweichungen) aus dem gesamten übermittelten Änderungssatz enthält. Entsprechend kann die Logik für die Auflösung den gesamten Änderungssatz verarbeiten. Sie bestimmen anhand der Überladung von SubmitChanges(), die Sie aufrufen, und der Parameter, die Sie an diese übergeben, welche Option angewendet wird.

Im folgenden Code wird die einfachste Möglichkeit zum Auflösen aller Abweichungen gezeigt.

foreach (TeamMember teamMember in teamSite.TeamMembers)
{
    teamMember.TopTask = "Fiscal Planning";
}

try 
{
    teamSite.SubmitChanges();
}
catch (ChangeConflictException e) 
{
    teamSite.ChangeConflicts.ResolveAll();
    teamSite.SubmitChanges();
}

Der erste Aufruf der SubmitChanges()-Methode ist die parameterlose Überladung. Sie löst die Ausnahme aus, sobald der erste Parallelitätskonflikt erkannt wird. Daher werden mit dem Aufruf von ChangeConflictCollection.ResolveAll() nur alle Abweichungen aufgelöst, die bis zu diesem Punkt aufgezeichnet wurden. Befindet sich unter den übermittelten Änderungen ein weiterer Parallelitätskonflikt, löst daher der zweite Aufruf von SubmitChanges() die Ausnahme aus.

Im folgenden Beispiel wird ein etwas komplexerer Code für das Auflösen von Abweichungen gezeigt.

foreach (TeamMember teamMember in teamSite.TeamMembers)
{
    teamMember.TopTask = "Fiscal Planning";
}

try 
{
    teamSite.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException e) 
{
    foreach (ObjectChangeConflict changedListItem in teamSite.ChangeConflicts)
    {
        // If another user has changed properties of a non-manager,
        // leave that other user’s changes, except for the TopTask field.
        if (((TeamMember)changedListItem.Object).IsManager = false)
        {        
             foreach (MemberChangeConflict changedField in changedListItem.MemberConflicts)
            {
                if (changedField.Member.Name == "TopTask")
                {
                    changedField.Resolve(RefreshMode.KeepCurrentValues);
                }
                else
                {
                    changedField.Resolve(RefreshMode.OverwriteCurrentValues);
                }
            }
        }
        // But if another user has changed properties of a manager, let this
        // process’s changes override the other user’s changes.
        else
        {
            changedListItem.Resolve(RefreshMode.KeepCurrentValues);
        }    
    }

    teamSite.SubmitChanges();
} // end catch