0

I am trying to link two tables to each other that will be recognised in the database, Customer and Address for example. Where the Address is virtual in the Customer class and pulled through into a list at load to then be stored in the AddressId (at the moment just using the Controller and Views auto created from my classes by VS2013).

Is this possible? I am looking into this as creating SQL DBs just for testing can be long and this is a quick way to set up a backend DB, especially in testing.

Usually I would do this with stored procedures and SQL but wanted to try a code first ran database.

I have a Customer an Address class, and a CustAddInitializer class, however unless I explicitly state the Id of the address class, the address class won't be recognised in the customer table.

Thanks in advance, example code below.

public class Customer
{
    [Key]
    public int CustomerId { get; set; }
    [Required(ErrorMessage = "First name is required")]
    [Display(Name = "First Name")]
    [MaxLength(30)]
    public string FirstName { get; set; }
    public int AddressId { get; set; }
    public virtual Address Address { get; set; }
}
public class Address
{
    [Key]
    public int AddressId { get; set; }
    [Required(ErrorMessage = "Street is required")]
    [Display(Name = "Street")]
    [MaxLength(30)]
    public string Street { get; set; }
}

public class CustAddInitializer : DropCreateDatabaseIfModelChanges<SomeContext>
{
    protected override void Seed(SomeContext context)
    {
        var customers = new List<Customer>
            {
                new Customer 
                { 
                    FirstName="Joe"
                }
            };
        customers.ForEach(tmp => context.Customers.Add(tmp));
        context.SaveChanges();

        var addresses = new List<Address>
        {
            new Address
            {
                Street="Joe Street"
            }
        };
        addresses.ForEach(tmp => context.Addresses.Add(tmp));
        context.SaveChanges();
    }
}

public class SomeContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Address> Addresses { get; set; }
    //tables will be created non-plural whenn constructed from code
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}
0

2 Answers 2

1

I'm not sure I 100% understand the question but if you are saying the link between the two tables isn't working in your CustAddInitializer that is because you fail to update the AddressId property on the Cust objects. This in turn would need to be pushed back through to the database. Once you have saved the Addresses to the your list should be updated with Addresses with relevant Ids. You can then Attach relevant Cust objects to the context update the AddressId property and SaveChanges again.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes that's what I was getting at, I think, sorry for the poor explanation, late here. The issue is that address isn't identifiable from the customer table, so on the Customer View Index, the AddressId is blank. In which class should I do this? As the Initializer is only called once through the asax. I was thinking there was an issue with my Customer class, perhaps missing an annotation or other link to the Address class to pull it through. Especially so that if I made a new Customer through the View, the address could be linked.
Do it in the CustAddInitializer. If you debug this calss you will see the Address objects will be poopulated with an AddressId after you call context.SaveChanges(). I would switch the order around. Add the addresses first so that you have the Ids and then for each Customer you add you can set the AddressId (this is your foreign key field) before you add the Customer. If you dont want to swap them around then you will have to Update the AddressId on the relevant Custome object and update this on the context.
1

I think the problem here is that you are specifying AddressId in your customer class. There is no need for that as you are specifying an address. Entity Framework will automatically manage the AddressId field for you.

In your initialiser, you don't join the address to the customer. If you wanted to do this then you could do:

//Create Joes Address
Address joesAddress = new Address() { Street = "Joes Street" };
// Create Joe
context.customers.Add(new Customer() { FirstName = Joe, Address = joesAddress};
// Save changes (will save both entities to the DB)
context.SaveChanges();

I would always add the client Navigation property Customer onto the Address as well to show if it is a 1 to 1 or 1 to Many relationship.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.