Birçok Varlık Çerçevesine Çok Ekleme / Güncelleme. Nasıl yaparım?


104

EF4 kullanıyorum ve yeni. Projemde çoktan çoğa var ve nasıl ekleneceğini veya güncelleneceğini çözemiyorum. Nasıl kodlanması gerektiğini görmek için küçük bir proje oluşturdum.

3 masam olduğunu varsayalım

  1. Sınıf: ClassID-ClassName
  2. Öğrenci: Öğrenci Kimliği-Adı-Soyadı
  3. StudentClass: StudentID-ClassID

Tüm ilişkiyi ekledikten ve modeli model tarayıcısı aracılığıyla güncelledikten sonra StudentClass'ın görünmediğini fark ettim, bu varsayılan davranış gibi görünüyor.

Şimdi hem Ekleme hem de Güncelleme yapmam gerekiyor. Bunu nasıl yapıyorsun? Örnek indirebileceğim herhangi bir kod örneği veya bağlantı ya da 5 dakikanızı ayırabilir misiniz?

Yanıtlar:


139

Varlıklar (veya nesneler) açısından Class, bir koleksiyonu olan Studentsbir Studentnesneye ve bir koleksiyonu olan bir nesneye sahipsiniz Classes. Senin bu yana StudentClasstablosu yalnızca kimlikleri ve hiçbir ekstra bilgiler içerir, EF katılmadan tablo için bir varlık oluşturmaz. Doğru davranış budur ve beklediğiniz de budur.

Şimdi, ekleme veya güncelleme yaparken nesneler açısından düşünmeye çalışın. Örneğin, iki öğrencili bir sınıf eklemek istiyorsanız, Classnesneyi, Studentnesneleri oluşturun, öğrencileri sınıf Studentskoleksiyonuna ekleyin, Classnesneyi bağlama ekleyin ve şunu arayın SaveChanges:

using (var context = new YourContext())
{
    var mathClass = new Class { Name = "Math" };
    mathClass.Students.Add(new Student { Name = "Alice" });
    mathClass.Students.Add(new Student { Name = "Bob" });

    context.AddToClasses(mathClass);
    context.SaveChanges();
}

Bu, Classtabloda bir giriş, tabloda iki giriş Studentve StudentClassbunları birbirine bağlayan tabloda iki giriş oluşturacaktır .

Temelde güncellemeler için aynısını yaparsınız. Sadece verileri alın, koleksiyonlardan nesne ekleyip çıkararak grafiği değiştirin, arayın SaveChanges. Ayrıntılar için bu benzer soruyu kontrol edin .

Düzenle :

Yorumunuza göre, yeni bir Classtane eklemeniz Studentsve ona mevcut iki tane eklemeniz gerekir:

using (var context = new YourContext())
{
    var mathClass= new Class { Name = "Math" };
    Student student1 = context.Students.FirstOrDefault(s => s.Name == "Alice");
    Student student2 = context.Students.FirstOrDefault(s => s.Name == "Bob");
    mathClass.Students.Add(student1);
    mathClass.Students.Add(student2);

    context.AddToClasses(mathClass);
    context.SaveChanges();
}

Her iki öğrenci de zaten veri tabanında olduğu için eklenmeyecekler, ancak artık Studentskoleksiyonda oldukları Classiçin StudentClasstabloya iki giriş eklenecek .


Merhaba, Cevabınız için teşekkürler Senaryom, sınıfa 1 giriş ve x olarak Öğrenci Sınıfına örnek 2 giriş eklemem gerektiği ve Öğrenci'ye giriş yapmam. Bunu nasıl yaptığım kafam karıştı
kullanıcı9969

BU BİR TEDAVİ ÇALIŞTI. Güncellemeyle ilgili olarak, yapmam gereken özel bir şey var mı? Örneğin, örneğin className'i güncellemek.
user9969

3
Bu, eklenmesi gereken öğelerin veritabanından getirilmesi için bir ek yük getirecektir. İliştirme yöntemi yalnızca bir ilişki eklemek için kullanılabilir. Bkz msdn.microsoft.com/en-us/data/jj592676.aspx ve ayrıca stackoverflow.com/questions/11355019/...
Gnomo

3
AddToClasses Sınıf için DbSet mi?
Jo Smo

1
Koleksiyonlarınızı Sınıf ve Öğrenci için kurucularda başlatmayı unutmayın. Örneğin: public Class () {this.Students = new HashSet <Student> (); }
user1040323

40

Güncelleme için bunu deneyin:

[HttpPost]
public ActionResult Edit(Models.MathClass mathClassModel)
{
    //get current entry from db (db is context)
    var item = db.Entry<Models.MathClass>(mathClassModel);

    //change item state to modified
    item.State = System.Data.Entity.EntityState.Modified;

    //load existing items for ManyToMany collection
    item.Collection(i => i.Students).Load();

    //clear Student items          
    mathClassModel.Students.Clear();

    //add Toner items
    foreach (var studentId in mathClassModel.SelectedStudents)
    {
        var student = db.Student.Find(int.Parse(studentId));
        mathClassModel.Students.Add(student);
    }                

    if (ModelState.IsValid)
    {
       db.SaveChanges();
       return RedirectToAction("Index");
    }

    return View(mathClassModel);
}

bu benim günümü kurtardı teşekkür ederim !!! öğe olan anahtar kısımdır. Koleksiyon (i => i.Öğrenciler) .Load (); bölüm
Gerrie Pretorius

Sadece bir yan not, bunu yaparken bir InvalidOperationException vardı, benim varlığım gibi bir şey bağlamda mevcut değildi. Bununla başa çıkmak için context.MyEntityCollection.Attach (myEntity) 'yi aradım.
Kilazur

Bunu asla anlayamazdım. Çok teşekkürler.
Jared Beach

1
Teşekkürlerimi buraya eklememe izin verin. Bu görevi yerine getirmeye çalışırken son 4 günde 130 satırdan fazla kod yazdım ve test ettim ama yapamadım. Bunu denedim ve her şey mükemmel çalıştı. Öğe değişkenini oluşturmanın amacını anlamadığım ve sonra onu hiç kullanmamama rağmen, işe yaradığına sevindim! Bir milyon bajillion teşekkürler !!!! :)
Dude-Dastic

Sorunun Ekle VE Güncelle olduğu düşünülürse, bu cevap soruyu ve kabul edilen cevabı tamamlar. Çok teşekkür ederim!
Vahx

5

Deneyimlerimi buna eklemek istedim. Aslında EF, bağlama bir nesne eklediğinizde, tüm alt öğelerin ve ilgili varlıkların durumunu Eklendi olarak değiştirir. Buradaki kuralda küçük bir istisna olsa da: alt öğeler / ilgili varlıklar aynı bağlam tarafından izleniyorsa, EF bu varlıkların var olduğunu anlar ve bunları eklemez. Örneğin, çocukları / ilgili varlıkları başka bir bağlamdan veya bir web kullanıcı arayüzünden yüklediğinizde ve sonra evet, EF bu varlıklar hakkında hiçbir şey bilmediğinde ve gidip hepsini eklediğinde sorun ortaya çıkar. Bundan kaçınmak için, varlıkların anahtarlarını alın ve onları bulun (örneğin context.Students.FirstOrDefault(s => s.Name == "Alice")), eklemeyi yapmak istediğiniz bağlamda).


3

Yalnızca yabancı anahtarların söz konusu olduğu çoktan çoğa ilişkisini işlemek için aşağıdaki yolu kullanıyorum.

Yani eklemek için :

public void InsertStudentClass (long studentId, long classId)
{
    using (var context = new DatabaseContext())
    {
        Student student = new Student { StudentID = studentId };
        context.Students.Add(student);
        context.Students.Attach(student);

        Class class = new Class { ClassID = classId };
        context.Classes.Add(class);
        context.Classes.Attach(class);

        student.Classes = new List<Class>();
        student.Classes.Add(class);

        context.SaveChanges();
    }
}

İçin silme ,

public void DeleteStudentClass(long studentId, long classId)
{
    Student student = context.Students.Include(x => x.Classes).Single(x => x.StudentID == studentId);

    using (var context = new DatabaseContext())
    {
        context.Students.Attach(student);
        Class classToDelete = student.Classes.Find(x => x.ClassID == classId);
        if (classToDelete != null)
        {
            student.Classes.Remove(classToDelete);
            context.SaveChanges();
        }
    }
}

1

Varlık çerçevesinde nesne bağlama eklendiğinde durumu Eklendi olarak değişir. EF ayrıca nesne ağacına eklenecek her nesnenin durumunu değiştirir ve bu nedenle ya birincil anahtar ihlali hatası alırsınız ya da tabloya yinelenen kayıtlar eklenir.


2
Lütfen yeterince ayrıntı vermek için düzenleyin , böylece bir kullanıcı yanıtı almak için blogunuzu ziyaret etmek zorunda kalmaz.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.