none
Entity framework object context saves new entities that were not added RRS feed

  • Question

  • I have been working with Entity Framework (VS2010 Framework 4.0) in my proyect. I had some trouble with using a different object context per form. What I did then, was to create a object context in the Main Menu Form (stays opened) and everytime I create and show one form, I pass that object context to this new form. Example:

     public partial class frm_Menu : Base
    {
        public Sistema_financiero_Entities db = new Sistema_financiero_Entities();
    
        private void cancelarCuotaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frm_Cancelacion_Cuota Form1 = new frm_Cancelacion_Cuota();
            Form1.db = db;
            Form1.Show();
        }
    }

    Ok, that solution worked fine until now because I needed to use and pass objects throw the differents forms sometimes, and if the objects contexts were different, I got an error.

    Now, I have detected a huge issue using it this way. I have a form, where I can pay for the different installments of a loan. I´ll attach an image so then you can see what I´m talking about.

    http://www.imagetoo.com/images/sinttujsj.png

    There, you select the different installments you want to pay for. Then, you introduce the value you will finally pay in "Total cobrado". Here is the important thing: When the checkbox image is checked (the blue one - already checked in the image), I create a "payment" entity per installment. Every "payment" object is stored in a list. If I uncheck it, I can change the value and the same thing is done. Obviously, I´m clearing the list before doing a list.Clear();. Then, one the checkbox checked, I can press "Aceptar" (accept). There I add to the database every "payment"(PAGO) in the list. After that, I save all changes.

    foreach (Pago p in Lista_nuevos_pagos)
    {
        db.AddToPago(p);
    }
    try
    {
        db.SaveChanges();
        this.Close();
    }

    My problem, is that it´s not only adding those "payments" in the list but the other "payments" entities that were in the list before clearing it. I reach the conclusion that when I clear the list, the objects remains in the object context. I thought that if the entity is not in the database, I have to Add it to the entity in the object context as I did with pago (db.AddToPago(p);).

    I wanted to ask you guys how can I solve this issues. I solved it now doing this:

    private void cancelarCuotaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Sistema_financiero_Entities db = new Sistema_financiero_Entities();
            frm_Cancelacion_Cuota Form1 = new frm_Cancelacion_Cuota();
            Form1.db = db;
            Form1.Show();
        }

    Instead of creating just one global db for all forms, I create one in the Main Menu for every form. Then, in that form closed event, I dispose that object context. Then, when i check the checkbox image, before creating the "payments", I delete every "Pago" entity from the object context:

    foreach (Pago p in Lista_nuevos_pagos)
            {
                db.DeleteObject(p);
            }
    
    Lista_nuevos_pagos.Clear();

    Doing this works correctly, but I´m still having trouble with some other created entities (Installments) that are not deleted when I clear a list. I think I´m doing it wrongly, thats why I need some direction to use EF correctly. I really need to get this done really soon, I don´t have too much time to read EF tutorials.

    Just in case, this is how I create every "Pago" (payment)

    Pago p = new Pago();                                                    
    p.desc_aumento_intereses = nudwb1.Value;                            
    p.desc_aumento_punitorios = nudwb2.Value; 
    p.desc_aumento_gastos = nudwb3.Value;                           
    p.desc_aumento_comision = nudwb4.Value;
    p.cotizacion = ntxt_Cotizacion.Value;
    p.fecha_hora = fecha_hora;
    
    Cuota c = new Cuota();
    string name = tbx.Name.Substring(tbx.Name.IndexOf("-") + 1);
    int nro_cuota = Convert.ToInt32(name);
    c = Lista_cuotas_cobrar.Where(x => x.num_cuota == nro_cuota).First();
    
    p.Cuota.Add(c);

    Thank you for reading, I know this is a lot of info. Hope some guide soon..

    Thursday, January 17, 2013 11:25 AM

Answers

  • Yes, they are automatically attached after db.AddToPago(p); call. When you create and add entity, EF starts this entity tracking and it will be saved to database, but if it will be detached before save, change tracking for this entity will be disabled and it will be ignored during commit. Usually detach affects related entities too, but I do not remember what are rules for them.

    As for one or many contexts, usually people use one context per unit of work, especially in web applications. For desktop applications it is little bit inconvenient, because requires always keep in mind when attach and when detach entity, but helps to prevent garbage in context and easily write some features, e.g. retry on database error.

    • Marked as answer by Andres G B Thursday, January 17, 2013 6:51 PM
    Thursday, January 17, 2013 2:46 PM

All replies

  • Are you saving these new records or they are temporary? If they were created and not yet saved to db, you could try to detach instead of delete. If records were physically saved to db, EF will delete related entities only if cascade delete behaviour was specified for them and only thoose related records, that were loaded into memory.

    • Proposed as answer by san Sanz Thursday, January 17, 2013 12:25 PM
    Thursday, January 17, 2013 12:21 PM
  • hi you need do like this

    Form1.db.SaveChanges()


    By Sanz. -- If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".

    Thursday, January 17, 2013 12:26 PM
  • When I create every Pago, they are temporary. I just want to save them when I do this:

    foreach (Pago p in Lista_nuevos_pagos)
    {
        db.AddToPago(p);
    }
    try
    {
        db.SaveChanges();
        this.Close();
    }

    I never attach or detach to the context. Is it attached automatically when I create an object of an entity?

    I was thinking that maybe, this is happening because Cuota has a list of pagos and Pagos has a list of Cuotas. Then, when I select a loan, I do

    List_cuotas = db.Cuota.Where(x => x.loan.id_loan = id_loan).ToList();

    So, when I create a Pago, I´m assigning a Cuota to that Pago. Maybe, when I do

    db.SaveChanges();

    Entity framework detects that that Cuotas were modified and it´s saving their Pago´s.

    What do you think? And how do you think I should use the objects contexts?


    • Edited by Andres G B Thursday, January 17, 2013 2:08 PM spelling
    Thursday, January 17, 2013 1:00 PM
  • Yes, they are automatically attached after db.AddToPago(p); call. When you create and add entity, EF starts this entity tracking and it will be saved to database, but if it will be detached before save, change tracking for this entity will be disabled and it will be ignored during commit. Usually detach affects related entities too, but I do not remember what are rules for them.

    As for one or many contexts, usually people use one context per unit of work, especially in web applications. For desktop applications it is little bit inconvenient, because requires always keep in mind when attach and when detach entity, but helps to prevent garbage in context and easily write some features, e.g. retry on database error.

    • Marked as answer by Andres G B Thursday, January 17, 2013 6:51 PM
    Thursday, January 17, 2013 2:46 PM
  • Thank you for your explanation. Now I get it. I know how it works. I will have to be careful and detach any of the temporary entity objects.
    Thursday, January 17, 2013 6:50 PM