Aktualisierung des Entity Frameworks mit verwandter Entität

asp.net entity-framework foreign-keys

Frage

Ich verwende die EF, um zu versuchen, eine Entität mit ASP.NET zu aktualisieren. Ich erstelle eine Entität, setze deren Eigenschaften ein und übergebe sie an die EF auf einer separaten Ebene mit der ID, damit die Änderung übernommen werden kann. Ich mache das, weil ich nur die ID der Entität speichere, wenn sie an die UI-Steuerelemente gebunden ist.

Alles funktioniert für Standardeigenschaften, aber ich kann die Category.ID eines Produkts (einer verwandten Entität) nicht aktualisieren. Ich habe EntityKey, EntityReference und einige andere probiert, aber die Kategorie-ID wird nicht gespeichert. Das ist was ich habe:

Product product = new Product();
product.CategoryReference.EntityKey = new EntityKey("ShopEntities.Categories", "CategoryID", categoryId);
product.Name = txtName.Text.Trim();
... other properties
StockControlDAL.EditProduct(productId, product);

public static void EditProduct(int productId, Product product) {
 using(var context = new ShopEntities()) {
     var key = new EntityKey("ShopEntities.Products", "ProductID", productId);
     context.Attach(new Product() { ProductID = productId, EntityKey = key });
     context.AcceptAllChanges();
     product.EntityKey = key;
     product.ProductID = productId;
     context.ApplyPropertyChanges("ShopEntities.Products", product);
     context.SaveChanges();
 }
}

Ich möchte die EF wirklich verwenden, aber ich habe anscheinend Probleme mit ASP.NET.

Akzeptierte Antwort

Dies ist eine akzeptierte Antwort auf diese Frage. Stark typisiertes ASP.NET-MVC mit Entity Framework

context.AttachTo(product.GetType().Name, product);
ObjectStateManager stateMgr = context.ObjectStateManager;
ObjectStateEntry stateEntry = stateMgr.GetObjectStateEntry(model);
stateEntry.SetModified();
context.SaveChanges();

Hast du das ausprobiert?

[Aktualisiert, Code oben funktioniert nicht]

Dies ist eine kleine Erweiterungseigenschaft, die ich verwendet habe, sodass der nächste Codeblock einfacher zu verstehen ist:

public partial class Product
{
    public int? CategoryID
    {
        set
        {  
           CategoryReference.EntityKey = new EntityKey("ShopEntities.Categories", "CategoryID", value);
        }
        get
        {
            if (CategoryReference.EntityKey == null)
                return null;

            if (CategoryReference.EntityKey.EntityKeyValues.Count() > 0)
                return (int)CategoryReference.EntityKey.EntityKeyValues[0].Value;
            else
                return null;
        }
    }
}

und das hat für mich funktioniert (diesmal sicher):

System.Data.EntityKey key = new System.Data.EntityKey("ShopEntities.Products", "ProductID", productId);
        object originalItem;   

        product.EntityKey = key;
        if (context.TryGetObjectByKey(key, out originalItem))
        {
            if (originalItem is EntityObject &&
                ((EntityObject)originalItem).EntityState != System.Data.EntityState.Added)
            {
                Product origProduct = originalItem as Product;   
                origProduct.CategoryID == product.CategoryID;//set foreign key again to change the relationship status           
                context.ApplyPropertyChanges(
                    key.EntitySetName, product);

            }
        }context.SaveChanges();

Sicher sieht es hackig aus. Ich denke, der Grund liegt darin, dass die EF-Beziehungen den Status als Entitäten haben (geändert, hinzugefügt, gelöscht) und EF basierend auf diesem Status den Wert der Fremdschlüssel ändert oder die Zeile löscht, wenn viele zu viele Beziehungen vorliegen. Aus irgendeinem Grund (weiß nicht warum) wird der Beziehungsstatus nicht wie der Eigenschaftsstatus geändert. Deshalb musste ich den CategoryReference.EntityKey auf originalItem setzen, um den Status der Beziehung zu ändern.


Beliebte Antwort

Der Grund dafür ist zweifach.

  1. Um eine Referenz (dh Product.Category) zu aktualisieren, müssen Sie auch den ursprünglichen Referenzwert im Kontext haben.
  2. ApplyPropertyChanges (...) gilt nur für reguläre / skalare Eigenschaften der Entität. Die Referenz bleibt unverändert

Also würde ich so etwas tun (Beachten Sie, dass dieser Code einen Trick namens Stub-Entitäten verwendet , um zu vermeiden, dass sich EntityKeys herumtreiben).

Product product = new Product();
// Use a stub because it is much easier.
product.Category = new Category {CategoryID = selectedCategoryID};
product.Name = txtName.Text.Trim();
... other properties

StockControlDAL.EditProduct(productId, originalCategoryID);


public static void EditProduct(Product product, int originalCategoryID ) {
 using(var context = new ShopEntities()) 
 {
     // Attach a stub entity (and stub related entity)
     var databaseProduct = new Product { 
             ProductID = product.ProductID, 
             Category = new Category {CategoryID = originalCategoryID}
         };
     context.AttachTo("Products", databaseProduct);

     // Okay everything is now in the original state
     // NOTE: No need to call AcceptAllChanges() etc, because 
     // Attach puts things into ObjectContext in the unchanged state

     // Copy the scalar properties across from updated product 
     // into databaseProduct in the ObjectContext
     context.ApplyPropertyChanges("ShopEntities.Products", product);

     // Need to attach the updated Category and modify the 
     // databaseProduct.Category but only if the Category has changed. 
     // Again using a stub.
     if (databaseProduct.Category.CategoryID != product.Category.CategoryID)
     {
         var newlySelectedCategory = 
                 new Category {
                     CategoryID = product.Category.CategoryID
                 };

         context.AttachTo("Categories", newlySelectedCategory)

         databaseProduct.Category = newlySelectedCategory;

     }

     context.SaveChanges();
 }
}

Dies erledigt die Arbeit, es werden keine Tippfehler usw. angenommen.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum