0

EF 4.1 in MVC3 and Lazy loading, using code first model

I am using Membership API for creating an account. Once the account is created successfully. I redirect to create a Contact record automatically. contactId (auto database generated), userid (storing the user id that was generated by membership api)

The models are:

public class Contact
{
   public int ContactID { set; get; }
   public string UserId { set; get; }
   public string LastName { set; get; }
   public int? CompanyID { set; get; } // not sure if I need this as it will be NULL
   public virtual Company CompanyInfo { set; get; }
}

next the user can click on create Company link or logout & login later to create the company record.

public class Company
{    
  public int CompanyID { set; get; }
  public int ContactID { set; get; }
  public string CompanyName { set; get; }
  public virtual Contact Contacts { set; get; }
}

When the user decides to create company record, I am checking if company already exists, if exists I am just showing the contact information and the company information OR if not found I redirect to create company.

public ActionResult chckifCompanyFound()
    {
        int contactId = 1; //Assuming I retrieved the value 
        //I think I should get the data from Company table, if company data found then contact data could be retrieved using lazy loading? 
       Company c= db.Company.Include(c => c.Contacts).Where(x => x.ContactID == contactId).FirstOrDefault();
      if(c == null)
          //redirect to create company
      else
         // view data from c company object
    }

currently it shows an exception once it tries to create contact record after membership API creates an account. I create the record like this:
Contact contact = new Contact();
contact.UserId = userId;
contact.LastName = lastName;
db.Contacts.Add(contact);
db.SaveChanges();

Exception:
Unable to determine the principal end of an association between the types 'D.Models.Contact' and 'D.Models.Company'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

thank you so much!

2
  • Are you using pure code first or modeling it around an existing database? Also, your models don't make much sense to me.. how does a company have Contacts and a ContactId and Contacts have a Company but no CompanyId Commented Dec 21, 2011 at 22:55
  • I am using code first. With models, A company can have multiple contacts and contacts can be part of one company. Do you think I need to add companyId in the contact model, if yes why? I thought I can just use lazy loading to get company information through the contact model. appreciate if you can help me fix my models. Commented Dec 22, 2011 at 6:38

3 Answers 3

1

Try the following (from this link):

Contact cc = db.Contacts.Include( "CompanyInfo" ).Where(x => x.ContactID == product.ContactID).FirstOrDefault();
Sign up to request clarification or add additional context in comments.

Comments

1

Try replacing your models with these:

public class Contact
{
   public int ContactId { set; get; }
   public string UserId { set; get; }
   public int CompanyId { get; set; }
   public string LastName { set; get; }
   public virtual Company Company { set; get; }
}

public class Company
{    
  public int CompanyId { set; get; }
  public string CompanyName { set; get; }
  public virtual ICollection<Contact> Contacts { set; get; }
}

Your Contact needs a CompanyId since it has only a single company related to it, and it will act as a foreign key between that contact and the company. The navigation property CompanyInfo will be used for the lazy loading. Your Company object only needs the Contacts collection because the Contact is where the relationship is created in the database.

To answer your question about the query I need more information... where does the product come in to play? I don't see it referenced from the contact or company, but if you want to get the Company of a Contact, simply do this:

var company = dbContext.Contacts.Find(userId).Company;
Console.WriteLine("Company Name: {0}", company.CompanyName);

1 Comment

Hi shuniar, I modified my original question, apologies for confusing. Could you please take a look at it and help me modify the models correctly as I am stuck and getting exceptions when running the code. I mentioned A company can have multiple contacts, plz ignore it. A company can have only one contact and via verse. Many Thx!
1

try:

 Contact cc = db.Contacts.Include(c=>c.CompanyInfo).Where(x => x.ContactID == product.ContactID).FirstOrDefault();

4 Comments

It highlights (c=>c.CompanyInfo) and shows the error: Error 1 Cannot convert lambda expression to type 'string' because it is not a delegate type
make sure you are using system.data.entity
still the object shows as null but the compilation error is gone. Do you know how to put the two queries together, maybe it will work then. thx
Try getting the contact seperatly via another query and see if it has the property when you get it on its own, if not you have a problem with your model/db/data

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.