-1

My entity relationship is Customer > Address > Contacts. i am trying to update data in customer table and remove specific data from Address & Contacts tables and try to add again data in Address & Contacts tables.

customer id is FK in Address table and AddressID is FK in Contacts tables. so when i am inserting data in contact table then i have to pass AddressID value for contact table but how do i know what is the current AddressID because i remove one Address data and insert again whose ID is require for contact table to be inserted. whole things i am trying to do in one SaveChanges()

really i am in problem and do not understand how to solve it. here is my code.

private void button3_Click(object sender, EventArgs e)
{
    using (var db = new TestDBContext())
    {
    var existingCustomer = db.Customer
    .Include(a => a.Addresses.Select(x => x.Contacts))
    .FirstOrDefault(p => p.CustomerID == 5);

    existingCustomer.FirstName = "Test Customer123";

    existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList().ForEach(r => db.Addresses.Remove(r));
    existingCustomer.Addresses.Where(a => a.AddressID == 5).SelectMany(ad => ad.Contacts).Where(c=> c.ContactID==5).ToList().ForEach(r => db.Contacts.Remove(r));

    Addresses oAdrModel = new Addresses();
    oAdrModel.Address1 = "test xxx";
    oAdrModel.Address2 = "test xxx";
    oAdrModel.SerialNo = 3;
    oAdrModel.IsDefault = true;
    oAdrModel.CustomerID = 5;
    db.Addresses.Add(oAdrModel);
    int xx = oAdrModel.AddressID;

    Contacts ContactModel = new Contacts();
    ContactModel.Phone = "XX-1111111-33";
    ContactModel.Fax = "XX-1-1111111";
    ContactModel.SerialNo = 4;
    ContactModel.IsDefault = true;
    //ContactModel.AddressID = 5;
    db.Contacts.Add(ContactModel);

    db.SaveChanges();
    }
}

ContactModel.AddressID whose value is not known which causing problem.

one way i can think about that i can insert data into address table and after that i have call SaveChanges() then i can get address ID which i can later insert into contact table. i am looking for best suggestion and guide line to handle this issue. thanks

Full Working code

using (var db = new TestDBContext())
{
    //db.Database.Log = s => MyLogger.Log("EFApp", s);

    var existingCustomer = db.Customer
    .Include(a => a.Addresses.Select(x => x.Contacts))
    .FirstOrDefault(p => p.CustomerID == 5);

    existingCustomer.FirstName = "Test Customer123";

    existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList().ForEach(r => db.Addresses.Remove(r));
    existingCustomer.Addresses.Where(a => a.AddressID == 5).SelectMany(ad => ad.Contacts).Where(c=> c.ContactID==5).ToList().ForEach(r => db.Contacts.Remove(r));

    Addresses oAdrModel = new Addresses();
    oAdrModel.Address1 = "test xxx";
    oAdrModel.Address2 = "test xxx";
    oAdrModel.SerialNo = 3;
    oAdrModel.IsDefault = true;
    oAdrModel.CustomerID = 5;
    db.Addresses.Add(oAdrModel);
    db.SaveChanges();
    int CurAddressID = oAdrModel.AddressID;

    Contacts ContactModel = new Contacts();
    ContactModel.Phone = "XX-1111111-33";
    ContactModel.Fax = "XX-1-1111111";
    ContactModel.SerialNo = 4;
    ContactModel.IsDefault = true;
    ContactModel.AddressID = CurAddressID;
    db.Contacts.Add(ContactModel);

    db.SaveChanges();
}

Current Code

See my full code and i am getting error Object reference not set

        using (var db = new TestDBContext())
        {
            //db.Database.Log = s => MyLogger.Log("EFApp", s);

            var existingCustomer = db.Customer
            .Include(a => a.Addresses.Select(x => x.Contacts))
            .FirstOrDefault(p => p.CustomerID == 5);

            existingCustomer.FirstName = "New Customer";

            existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList().ForEach(r => db.Addresses.Remove(r));
            existingCustomer.Addresses.Where(a => a.AddressID == 5).SelectMany(ad => ad.Contacts).Where(c=> c.ContactID==5).ToList().ForEach(r => db.Contacts.Remove(r));

            Addresses oAdrModel = new Addresses();
            oAdrModel.Address1 = "New test xxx";
            oAdrModel.Address2 = "New test xxx";
            oAdrModel.SerialNo = 3;
            oAdrModel.IsDefault = true;
            //oAdrModel.CustomerID = 5;
            existingCustomer.Addresses.Add(oAdrModel);
            //db.Addresses.Add(oAdrModel);
            //db.SaveChanges();
            //int CurAddressID = oAdrModel.AddressID;

            Contacts ContactModel = new Contacts();
            ContactModel.Phone = "New XX-1111111-33";
            ContactModel.Fax = "New XX-1-1111111";
            ContactModel.SerialNo = 4;
            ContactModel.IsDefault = true;
            oAdrModel.Contacts.Add(ContactModel);

            //ContactModel.AddressID = CurAddressID;
            //db.Contacts.Add(ContactModel);

            db.SaveChanges();
        }

POCO classes for EF

public class CustomerBase
{
    public int CustomerID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [NotMapped]
    public string Address1 { get; set; }

    [NotMapped]
    public string Address2 { get; set; }

    [NotMapped]
    public string Phone { get; set; }

    [NotMapped]
    public string Fax { get; set; }

}

public class Customer : CustomerBase
{
    public virtual List<Addresses> Addresses { get; set; }
}

public class Addresses
{
    [Key]
    public int AddressID { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public bool IsDefault { get; set; }
    public int SerialNo { get; set; }
    public virtual List<Contacts> Contacts { get; set; }

    public int CustomerID { get; set; }
    //[ForeignKey("CustomerID")]
    public virtual Customer Customer { get; set; }
}

public class Contacts
{
    [Key]
    public int ContactID { get; set; }

    public string Phone { get; set; }
    public string Fax { get; set; }
    public bool IsDefault { get; set; }
    public int SerialNo { get; set; }
    public int AddressID { get; set; }

    //[ForeignKey("AddressID")]
    public virtual Addresses Customer { get; set; } 

}

this line oAdrModel.Contacts.Add(ContactModel); throwing error Object reference not set to an instance of an object

what is wrong in my code ? please help me to fix it.

Mou
  • 15,673
  • 43
  • 156
  • 275
  • You can use navigation property which should be present on Contacts entity. ContactModel.Address = oAdrModel. – Evk Nov 04 '16 at 12:08

3 Answers3

4

Rather than setting parent Id properties and adding the new entities directly to the corresponding DbSet, just add them to the corresponding parent collection:

Addresses oAdrModel = new Addresses() { Contacts = new List<Contacts>() };
oAdrModel.Address1 = "test xxx";
oAdrModel.Address2 = "test xxx";
oAdrModel.SerialNo = 3;
oAdrModel.IsDefault = true;

existingCustomer.Addresses.Add(oAdrModel);

Contacts ContactModel = new Contacts();
ContactModel.Phone = "XX-1111111-33";
ContactModel.Fax = "XX-1-1111111";
ContactModel.SerialNo = 4;
ContactModel.IsDefault = true;

oAdrModel.Contacts.Add(ContactModel);
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • u did not understand my question. when i am inserting new contact then i need address id because address and contact has relation. probably i have to use SaveChanges twice in this situation. – Mou Nov 04 '16 at 14:28
  • address id is FK in contact table. i am not setting parent Id rather i am setting value for FK fields in child table. how could i get value for newly added data for FK field without saving to db? – Mou Nov 04 '16 at 14:30
  • 1
    I did understand the question, you did not understand the answer. By parent I meant `CustomerID` in `Addresses` and `AddressID` in `Contact`. Anyway, the answer is correct, I've tested it before posting, you could at least try it. – Ivan Stoev Nov 04 '16 at 14:41
  • without saving new address data in db table how could we get new address id ? i have to store new address id in contact table and that is why we need to save address data in table to get its id. am i right ? – Mou Nov 05 '16 at 15:59
  • You are not getting the point, you don't need to assign `AddressID` field. When you add the address to `oAdrModel.Contacts` (note the `oAdrModel`, not `db`), during `SaveChanges` EF will assign the correct `AddressID` for you. Again, rather than commenting and asking, you could have just ran the above snippet (as I did before posting it). If you did so, you would have seen that it works correctly. – Ivan Stoev Nov 05 '16 at 16:53
  • one request that still it is not clear to what u r trying to say. so would please see my code and post here after rectification. thanks – Mou Nov 05 '16 at 19:55
  • from your code it seems i do not have to assign value for address id or customer id rather EF will do it for me if i add address and contact to model collection instead. so i need to change these two line from `db.Addresses.Add(oAdrModel); and db.Contacts.Add(ContactModel);` to `existingCustomer.Addresses.Add(oAdrModel); and oAdrModel.Contacts.Add(ContactModel);` am i right ? – Mou Nov 05 '16 at 20:02
  • Correct, you've got it :) – Ivan Stoev Nov 05 '16 at 20:15
  • i also gave u the up vote and later will mark your answer after test it. – Mou Nov 05 '16 at 20:20
  • i follow your code and this line `oAdrModel.Contacts.Add(ContactModel);` throwing error called "Object reference not set to an instance of an object." just do not understand what was the fault in code. – Mou Nov 07 '16 at 09:41
  • The problem is that `Contacts` property is not initialized for new `Addresses` object, hence the exception. See the updated code which fixes that. – Ivan Stoev Nov 07 '16 at 10:26
  • so should i do the same for customer address ? i did not do such things for address for customer but it is working without initialization.....how? please share the knowledge. thanks – Mou Nov 07 '16 at 10:29
  • No, because it is existing. If the property was `null`, you won't be able to execute the 2 lines staring with `existingCustomer.Addresses.Where(...`. But if you create a new `Customer`, then yes, you need to do the same. – Ivan Stoev Nov 07 '16 at 10:43
0

You can do a two step db.SaveChanges();

like this:

Addresses oAdrModel = new Addresses();
oAdrModel.Address1 = "test xxx";
oAdrModel.Address2 = "test xxx";
oAdrModel.SerialNo = 3;
oAdrModel.IsDefault = true;
oAdrModel.CustomerID = 5;
db.Addresses.Add(oAdrModel);
int xx = oAdrModel.AddressID;
db.Addresses.Add(oAdrModel);

db.SaveChanges();

Contacts ContactModel = new Contacts();
ContactModel.Phone = "XX-1111111-33";
ContactModel.Fax = "XX-1-1111111";
ContactModel.SerialNo = 4;
ContactModel.IsDefault = true;
ContactModel.AddressID = oAdrModel.AddressID;
db.Contacts.Add(ContactModel);

db.SaveChanges();
-1
Addresses oAdrModel = new Addresses();
oAdrModel.Address1 = "test xxx";
oAdrModel.Address2 = "test xxx";
oAdrModel.SerialNo = 3;
oAdrModel.IsDefault = true;
oAdrModel.CustomerID = 5;
db.Addresses.Add(oAdrModel);
int xx = oAdrModel.AddressID;

Contacts ContactModel = new Contacts();
ContactModel.Phone = "XX-1111111-33";
ContactModel.Fax = "XX-1-1111111";
ContactModel.SerialNo = 4;
ContactModel.IsDefault = true;
//ContactModel.AddressID = 5;
ContactModel.Address = oAdrModel
db.Contacts.Add(ContactModel);

db.SaveChanges();

Where Address should be a virtual Addresses and has a joined to AddressID:

public class ContacModel{
{
    public  int AddressID { get; set; }
    [ForeignKey("AddressID")]
    public virtual Addresses Address { get; set; }
}
krlzlx
  • 5,752
  • 14
  • 47
  • 55
Paweł Haracz
  • 52
  • 1
  • 3
  • without `db.SaveChanges();` how can u get newly inserted address id ? – Mou Nov 04 '16 at 12:47
  • because Entity framework self identifies dependency for relationship and at first insert related entities and lastly insert main Entity. a similar question : http://stackoverflow.com/questions/4253165/insert-update-many-to-many-entity-framework-how-do-i-do-it – Paweł Haracz Nov 04 '16 at 13:37
  • run the above code then u can see if u do not save new address then u can not get address id of new added data. – Mou Nov 04 '16 at 13:46
  • yes, but your address has been a link with contract, and next you can be use ContactModel.AddressID. if you have turn on lazy loading, Entity Framework automatically query the database on the id associated to this Contract, and return you addressId – Paweł Haracz Nov 04 '16 at 14:06