wake-up-neo.com

Verwenden Sie linq, um eine direkte Aktualisierung ohne Auswahl zu generieren

Guten Tag allerseits.

Ich lerne immer noch LINQ, also vergib mir, wenn das naiv ist. Wenn Sie direkt mit SQL arbeiten, können Sie Aktualisierungsbefehle mit Bedingungen generieren, ohne eine select-Anweisung auszuführen.

Wenn ich mit linq arbeite, scheine ich dem Muster zu folgen:

  1. Entitäten auswählen
  2. Objekte ändern
  3. Änderungen einreichen

Was ich tun möchte, ist ein direktes Update mit linq und verzögerter Ausführung. Ist es möglich, dass die eigentliche Ausführung direkt im SQL erfolgt, ohne dass Daten an den Client übermittelt werden?

DataContext dc = new DataContext

var q = from product in dc.Products
        where product.Type = 1
        set product.Count = 0

dc.SubmitChanges

Im Wesentlichen verfügt LINQ also über alle Informationen, die es OHNE WÄHLEN benötigt, um einen Aktualisierungsbefehl zu erzeugen. Es würde die SQL ausführen:

Update Products Set Count = 0 Where Type = 1

Gibt es ein Schlüsselwort wie "set" in LINQ?

43
Spence

Nein, weder LINQ noch LINQ to SQL verfügen über satzbasierte Aktualisierungsfunktionen. 

In LINQ to SQL müssen Sie das zu aktualisierende Objekt abfragen, die Felder/Eigenschaften nach Bedarf aktualisieren und dann SubmitChanges () aufrufen. Zum Beispiel:

var qry = from product in dc.Products where Product.Name=='Foobar' select product;
var item = qry.Single();
item.Count = 0;
dc.SubmitChanges();

Wenn Sie das Dosieren durchführen möchten:

var qry = from product in dc.Products where Product.Type==1 select product;
foreach(var item in qry)
{
  item.Count = 0;
}
dc.SubmitChanges();

Alternativ können Sie die Abfrage auch selbst schreiben:

dc.ExecuteCommand("update Product set Count=0 where Type=1", null);
29
Randolpho

Sie können LINQ-to-SQL tatsächlich Aktualisierungsanweisungen generieren lassen:

Foo foo=new Foo { FooId=fooId }; // create obj and set keys
context.Foos.Attach(foo);
foo.Name="test";
context.SubmitChanges();

In Ihrer Dbml setzen Sie UpdateCheck = "Never" für alle Eigenschaften.

Dies erzeugt eine einzige Aktualisierungsanweisung , ohne dass zuvor eine Auswahl getroffen werden muss.

Ein Nachteil: Wenn Sie Name auf null setzen möchten, müssen Sie Ihr foo-Objekt mit einem anderen Wert initialisieren, damit Linq die Änderung erkennen kann:

Foo foo=new Foo { FooId=fooId, Name="###" };
...
foo.Name=null;

Wenn Sie während der Aktualisierung nach einem Zeitstempel suchen möchten, können Sie auch Folgendes tun:

Foo foo=new Foo { FooId=fooId, Modified=... }; 
// Modified needs to be set to UpdateCheck="Always" in the dbml
45
laktak

Das PLINQO ( http://plinqo.com ) Framework verwendet das LINQ-Batch-Update, um Updates durchzuführen

context.Task.Update(t => t.Id == 1, t2 => new Task {StatusId = 2});

Dies wird einen Update Task Set StatusId = 2 Where Id = 1 ausführen

3

Linq 2 SQL verfügt nicht über direkte SQL-Einfügungen zum Aktualisieren/Aktualisieren/Löschen. In V1 sind die einzigen Aktualisierungen, die Sie mit linq ausführen können, die Annahme, SubmmitChanges für den Kontext oder für den Fall, dass Sie auf SQL zugreifen.

Einige Leute haben jedoch versucht, diese Einschränkung von linq mit benutzerdefinierten Implementierungen zu überwinden.

Linq Batch-Update.

3
Pop Catalin

Verwenden Sie diese Erweiterungsmethode: EntityExtensionMethods.cs

public static void UpdateOnSubmit<TEntity>(this Table<TEntity> table, TEntity entity, TEntity original = null)
    where TEntity : class, new()
{
    if (original == null)
    {
        // Create original object with only primary keys set
        original = new TEntity();
        var entityType = typeof(TEntity);
        var dataMembers = table.Context.Mapping.GetMetaType(entityType).DataMembers;
        foreach (var member in dataMembers.Where(m => m.IsPrimaryKey))
        {
            var propValue = entityType.GetProperty(member.Name).GetValue(entity, null);
            entityType.InvokeMember(member.Name, BindingFlags.SetProperty, Type.DefaultBinder,
                original, new[] { propValue });
        }
    }

    // This will update all columns that are not set in 'original' object. For
    // this to work, entity has to have UpdateCheck=Never for all properties except
    // for primary keys. This will update the record without querying it first.
    table.Attach(entity, original);
}

Stellen Sie zur Verwendung sicher, dass das entity-Objekt, das Sie an die UpdateOnSubmit-Methode übergeben, über alle Primärschlüsseleigenschaften für den Datensatz verfügt, der aktualisiert werden soll. Diese Methode aktualisiert dann den Datensatz mit den verbleibenden Eigenschaften des entity-Objekts, ohne den Datensatz zuerst abzurufen.

Stellen Sie sicher, dass Sie nach dem Aufruf von UpdateOnSubmitSubmitChanges() aufrufen, damit die Änderungen übernommen werden.

0
orad

Sie können die Bibliothek Entity Framework Extensions verwenden. Sie unterstützt die Stapelaktualisierung und die Stapelzusammenführung. Die Bibliothek ist jedoch nicht kostenlos:

PM> Install-Package Z.EntityFramework.Extensions

using Z.EntityFramework.Plus;

...

dc.Products
    .Where(q => q.Type == 1)
    .Update(q => new Product { Count = 0 });
0
koryakinp