I want to create my first application using the EF 4.1 Code First Model. I want to model a magazine subscription but just want to check that my POCO classes are fit for purpose.
The following are my classes. Am I missing anything?
Should Customer be a member of Subscription or should it be just that List be a member of Customer?
Thanks.
public class Subscription
{
public int SubscriptionID { get; set; }
public string CardNumber { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public decimal NetPrice { get; set; }
public decimal Tax { get; set; }
public decimal Discount { get; set; }
public string PromotionalCode { get; set; }
public Customer Customer{ get; set; }
}
public class Customer {
public int CustomerID { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public PostalAddress PostalAddress { get; set; }
public string EmailAddress { get; set; }
public string Telephone { get; set; }
public string Mobile { get; set; }
public DateTime DateOfBirth { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string SecurityQuestion { get; set; }
public string SecurityAnswer { get; set; }
public bool Valid { get; set; }
public IList<Subscription> Subscriptions { get; set; }
public bool MailMarketing { get; set; }
public bool PartnerMailMarketing { get; set; }
}
public class PostalAddress
{
public int ID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string Postcode { get; set; }
public string Region { get; set; }
public string Country { get; set; }
}
If a Customer have X suscriptions, every suscription should have the customerID so you need that in your Suscription class (public int CustomerID {get; set;}).
OTOH, I think that you have to put that Customer reference as virtual and the suscription one (I don't know why).
Maybe Im wrong but that works for me.
Anyway, what's your problem?
Your models look correct. You don't necessarily need the Customer property in the Subscription class, but it does help if you want to retrieve a specific Subscription and then want to find the customer that is tied to that subscription. In that instance you can then do var customer = mySub.Customer instead of querying for a customer with the specific subscription id.
Related
This is the first time I have attempted to join information from one database to the other. I have a accounting database and a regular site database. Trying to keep them separate. I have a page that shows Transactions but am getting the information for a few of the columns from the regular database by way of Id's. Below is my Model. I am showing nothing in the fields for the items in the other database.
public class Transaction
{
[Key]
public Guid TransactionId { get; set; }
public string Description { get; set; }
public int? CompanyId { get; set; }
public Guid? VendorId { get; set; }
public string InCheckNumber { get; set; }
public string OutCheckNumber { get; set; }
public string InvoiceNumber { get; set; }
public string PurchaseOrderNumber { get; set; }
public Guid LedgerAccountId { get; set; }
public decimal? DebitAmount { get; set; }
public decimal? CreditAmount { get; set; }
public DateTime TransactionDate { get; set; }
public string ModifiedBy { get; set; }
public DateTime? ModifiedDate { get; set; }
public string SavedDocument { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public bool IsCredit { get; set; }
public bool IsDebit { get; set; }
public Guid Type { get; set; }
[ForeignKey("LedgerAccountId")]
public LedgerAccount LedgerAccount { get; set; }
[ForeignKey("CompanyId")]
public CompanyNames Company { get; set; }
[ForeignKey("VendorId")]
public Vendors Vendor { get; set; }
}
I have added the 'using' of the General.Entities to this model. Is there something else i need to add for this?
Thanks in advance.
UPDATE:
See Question - Link to answer of question
currently I have this two models:
Contact.cs
public class Contact
{
public int ConctactId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string City { get; set; }
}
PhoneNumber.cs
public class PhoneNumber
{
public int PhoneNumberId { get; set; }
public string Number { get; set; }
public string Description { get; set; }
public PhoneNumberTypeEnum EnumType { get; set; }
}
My question is, what is a correct way to alter these two so I can have multiple instances of PhoneNumber linked to one Contact? Also, later I would like to display all contacts in View with corresponding phone numbers.
Change your models as following
public class Contact
{
public int ConctactId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string City { get; set; }
public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
}
public class PhoneNumber
{
public int PhoneNumberId { get; set; }
public string Number { get; set; }
public string Description { get; set; }
public PhoneNumberTypeEnum EnumType { get; set; }
public int ContactId {get; set;}
public virtual Contact Contact{get; set;}
}
In simple relational terms, I want each entry of ContractDetails to be assigned to either a Site OR a Company, not both at the same time, and one of them must be selected or there is no link at all. I'm not quite sure how to represent this in entity framework. My Model at Present:
Company Model:
public class Company
{
public int ID { get; set; }
public string Company_Name { get; set; }
public string Company_Prefix { get; set; }
public virtual ICollection<Site> Sites { get; set; }
}
Contract Details Model:
public class ContractDetails
{
public int ContractDetailsID { get; set; }
public int ContractTypeID { get; set; }
public int ContractRenewalPeriodID { get; set; }
public int? CompanyID { get; set; }
public int? SiteID { get; set; }
[Required, StringLength(10)]
public string Reference { get; set; }
[Display(Name = "Contract Start Date"), DataType(DataType.Date)]
public DateTime? Contract_Start_Date { get; set; }
[Display(Name = "Contract End Date"), DataType(DataType.Date)]
public DateTime? Contract_End_Date { get; set; }
[Column(TypeName = "text")]
public string Notes { get; set; }
public string Direct_Debit_Reference { get; set; }
public virtual Company Company { get; set; }
public virtual Site Site { get; set; }
public virtual ContractType ContractType { get; set; }
public virtual ContractRenewalPeriod ContractRenewalPeriod { get; set; }
}
Site Model:
public class Site
{
public int ID { get; set; }
public string Site_Name { get; set; }
public string Site_TelephoneNumber { get; set; }
public string Site_City { get; set; }
public int CompanyID { get; set; }
public virtual Company Company { get; set; }
}
Just implement the IValidatableObject on ContractDetails class. On Validate method put the validation logic. If the object is not valid you must return a collection of ValidationResult. when saving the object, EF will execute the Validate method and verify that your ContractDetails object is coherent.
my model classes first:
public class Person
{
[Required, Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string LearntSkillsAndLevelOfSkills { get; set; }
public string ProfileImage { get; set; }
public string City { get; set; }
public string PhoneNr { get; set; }
[Required]
public string Email { get; set; }
public string Hobbys { get; set; }
public string SkillsToLearn { get; set; }
public string Stand { get; set; }
public int YearsOfWorkExperience { get; set; }
public string HobbyProjectICTRelated { get; set; }
public string ExtraInfo { get; set; }
public string Summary { get; set; }
public int UserId { get; set; }
[ForeignKey("UserId")]
public virtual UserProfile profile { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public Nullable<int> ID { get; set; }
public virtual Person personprofile { get; set; }
}
when i run this however it gives me this exception: The principal end of this association must be explicitly configured
i've searched this error but it doesn't clarify it for me... so i absolutely have no clue how to fix this. Basically i want to link my Person class to the Userprofiles so that i can create a login mechanism that automatically lets 1 person who makes an account on the site get 1 Profile to Edit to his own information. He's however not allowed to modify other people their accounts.
I hope this makes my problem clear and that somebody can help me :). i'm using EF 6 btw and i get the error in the class InitializeSimpleMembershipAttribute that comes standard with the MVC example of ASP.net
Greetings and thanks in advance,
Marijn
I managed to get it working with these codes in the models:
[Table("UserProfile")]
public class UserProfile
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual Person personprofile { get; set; }
}
public class Person
{
[ForeignKey("profile"), Key]
public int UserId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string LearntSkillsAndLevelOfSkills { get; set; }
public string ProfileImage { get; set; }
public string City { get; set; }
public string PhoneNr { get; set; }
[Required]
public string Email { get; set; }
public string Hobbys { get; set; }
public string SkillsToLearn { get; set; }
public string Stand { get; set; }
public int YearsOfWorkExperience { get; set; }
public string HobbyProjectICTRelated { get; set; }
public string ExtraInfo { get; set; }
public string Summary { get; set; }
public UserProfile profile { get; set; }
}
I work with EF for the first time so I don't know is situation like this normal or I have serious performance issues.
I have following situation:
Bellow are the classes that I have. Item is the main object here. So when I pull a list of Items from database I get for example 1000 items. And now each of this item has all properties filed with data. City contains Country, Country contains list of cities, User has list of created items, each item all data again, city, city has country, country list of cities etc etc...
Maybe I am worrying too much and I don't know should this object's contain all those data and does this make performance issues, or I am doing something wrong here?
public abstract class Item
{
[Key]
public int ItemId { get; set; }
public int ItemTypeId { get; set; }
public Guid UserId { get; set; }
public DateTime CreatedOnDate { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int? MediaId { get; set; }
public int CityId { get; set; }
public virtual City City { get; set; }
public virtual User User { get; set; }
public virtual ICollection<ItemInBoard> ItemsInBoard { get; set; }
public virtual ICollection<Like> Likes { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class City
{
public int CityId { get; set; }
public string Name { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
public int CountryId { get; set; }
public virtual Country Country { get; set; }
}
public class Country
{
public int CountryId { get; set; }
public string Name { get; set; }
public string CountryCode { get; set; }
public virtual ICollection<City> Cities { get; set; }
}
public class User
{
public Guid UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Gender { get; set; }
public DateTime? BirthDay { get; set; }
public string AboutMe { get; set; }
public int? MediaId { get; set; }
public int CityId { get; set; }
public virtual City City { get; set; }
public virtual ICollection<Item> Items { get; set; }
public virtual ICollection<Board> Boards { get; set; }
public virtual ICollection<Like> Likes { get; set; }
}
It is up to you. This is a concept called lazy loading. You can enable or disable lazy loading with this code:
context.Configuration.LazyLoadingEnabled = false;
context.Configuration.LazyLoadingEnabled = true;
When enabling this option none of the dependent entities will be loaded. To enforce dependent entities to load you can use the Include lambada expression like this:
var test = context.Tests.Include("SomeOtherDependentEntity");
Hope I got you and this is what you meant.
I would say that what you have is fine for general business logic.
When I have to do a lot of time sensitive processing in a read-only fashion I use SQL commands like this to get exactly and only exactly what I want.
public class myQueryClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
var context = new MyDbContext();
context.Database.SqlQuery<myQueryClass>("SELECT Property1 = acolumn, Property2 = acolumn2 FROM myTable WHERE something = somestate");