Nested entity models query issue - asp.net

i have 3 nested models: ApplicationUser(from entity framework), City and State.
ApplicationUser has city as foreign key and city has state as foreign key.
When I query a user, i get a user with all of its attributes including City as a related model but when i lookup into city, the related model State is null, all the others attributes are ok. Any clue?
This is StateModels
public class StateModels
{
public int Id { get; set; }
public string State { get; set; }
public string Abbreviation { get; set; }
}
This is CityModels
public class CityModels
{
public int Id { get; set; }
public string City { get; set; }
public int ZipCode { get; set; }
public virtual StateModels State { get; set; }
}
And this is ApplicationUser
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public virtual CityModels City { get; set; }
public string CompanyPhone { get; set; }
public string CompanyFax { get; set; }
public bool Validated { get; set; }
public bool Staff { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
This is how i try to get to the state object
ApplicationUser applicationUser = db.Users.Find(idUser);
var city = applicationUser.City; //object city is ok
var state = city.State; // this field is null, all others attributes are ok
In the db, all city registers have state id reference

Try this. db.Users.Find(idUser).Include(u=>u.City).Include(u=>u.City.State) and make sure you have all foreign keys are properly set.

Related

How to extend Application User to hold a collection of orders?

I'm trying to extend Application User (using Code-First) to hold a collection of orders, but I'm getting errors.
My Order class is
public class Order
{
public Order()
{
OrderDetails = new HashSet<OrderDetails>();
}
public int ID { get; set; }
public DateTime OrderDate { get; set; }
public string UserId { get; set; }
public bool IsDelivered { get; set; }
public bool IsReturned { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ICollection<OrderDetails> OrderDetails { get; set; }
}
And I'm trying to extend Application user like this
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Profession { get; set; }
public string TaxAuthority { get; set; }
public string TaxNumber { get; set; }
public string Address { get; set; }
public string PostalCode { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string Country { get; set; }
public string Phone { get; set; }
public string MobilePhone { get; set; }
public bool NewsLetterSubscribe { get; set; } = false;
public DateTime TimeStamp { get; set; } = DateTime.Now;
public ICollection<Order> Orders { get; set; }
}
And I'm getting the following errors:
QCMS.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
QCMS.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
Can you please help me to solve this problem?
UPDATE:
I'm using two db contexts. The one provided for Individual User Account (when the project is first created) and a second one named "qvModel" that is for all other database classes of my project.
public partial class qvModel : DbContext
{
public qvModel()
: base("name=qvModel")
{
}
//APPSETTINGS
public virtual DbSet<AdminLog> AdminLog { get; set; }
public virtual DbSet<WebLog> WebLog { get; set; }
//LANGUAGES
public virtual DbSet<Language> Languages { get; set; }
.
.
.
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<OrderDetails> OrderDetails { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Precision attribute for decimals
Precision.ConfigureModelBuilder(modelBuilder);
modelBuilder.Entity<Language>()
.HasMany(e => e.Brochures)
.WithRequired(e => e.Language)
.WillCascadeOnDelete(true);
.
.
.
modelBuilder.Entity<Order>()
.HasMany(c => c.OrderDetails)
.WithRequired(c => c.Order)
.WillCascadeOnDelete(true);
modelBuilder.Entity<ApplicationUser>()
.HasMany(c => c.Orders)
.WithRequired(c => c.User)
.WillCascadeOnDelete(true);
base.OnModelCreating(modelBuilder);
}
}
I found a solution that is very simple.
The solution is to inherit from IdentityDbContext like this
public class qvModel : IdentityDbContext<ApplicationUser>
{
public qvModel()
: base("name=qvModel")
{
}
I was also missing the following line from OnModelCreating
base.OnModelCreating(modelBuilder);
After these changes, my migration is working and I stopped getting the errors I mentioned.

Many to many with extra foreign key?

I want to generate a junction table between user and post and I want to have the userId in the post table.
I have this code
public class Post
{
public Post()
{
this.ApplicationUser = new HashSet<ApplicationUser>();
}
public int PostId { get; set; }
public string Message { get; set; }
public DateTime MessageDate { get; set; }
public virtual ApplicationUser User { get; set; } //this is the problem
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public ApplicationUser()
{
this.Posts = new HashSet<Post>();
}
public virtual ICollection<Post> Posts { get; set; }
}
I get the extra junction table and many-to-many relation between user and post. But this is wrong.
public virtual ApplicationUser User { get; set; }
This generates two UserId in the post table (applicationUser_id and User_id) and Post_PostId in the User table. I just want one extra field in the Post table, FK UserId.
I want three tables like this
Post
PostId
Message
Date
UserId FK
User
UserId
And the rest of the fields in asp.net identity user
UserPosts
UserId
PostId
User table
public partial class User
{
public User()
{
this.Posts = new HashSet<Post>();
this.UserPosts = new HashSet<UserPost>();
}
public int UserId { get; set; }
public string Username { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public virtual ICollection<UserPost> UserPosts { get; set; }
}
Post table
public partial class Post
{
public Post()
{
this.UserPosts = new HashSet<UserPost>();
}
public int PostId { get; set; }
public string Message { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<int> UserId { get; set; }
public virtual User User { get; set; }
public virtual ICollection<UserPost> UserPosts { get; set; }
}
and your mapping table, like this
your column 1) Id (pk), 2) UserId (fk) 3) PostId (fk)
using entity framework table have one primary key necessary.
UserPost table
public partial class UserPost
{
public int Id { get; set; }
public Nullable<int> UserId { get; set; }
public Nullable<int> PostId { get; set; }
public virtual Post Post { get; set; }
public virtual User User { get; set; }
}
Updated Code
modelBuilder.Entity<Post>().ToTable("userid table name");
this line add in below method of this class ApplicationDbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}

Get values to a dropdownlist associated to the UserId

I have an application that basically controls the expenses and income of a person, and an expense is associated with a type of expenditure, these types of expenditure can be created by the user and must differ from user to user.
Exemplifying best for the types of expenditure can have various options available and I can only pick one, this was implemented through a dropdownlist.
What was intended that each user had their types of expenditure and that they were different from each other, what I have is the following:
Model Expenses:
public class Expense
{
public int TipeExpenseId { get; set; }
public int ExpenseId { get; set; }
[Display(Name = "Descrição da Despesa")]
[Required]
public string ExpenseDescription { get; set; }
[Display(Name = "Valor")]
[Required]
public decimal ExpenseValue { get; set; }
public int PayementTypeId { get; set; }
[Display(Name = "Data")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",ApplyFormatInEditMode = true)]
[Required]
public DateTime Data { get; set; }
public ExpenseTipe ExpenseTipe { get; set; }
public PaymentType PaymentType { get; set; }
[Display(Name = "Comentário")]
public string Coment { get; set; }
[ForeignKey("ApplicationUserId")]
public virtual ApplicationUser User { get; set; }
public string ApplicationUserId { get; set; }
}
Model TipeExpense:
public int ExpenseTipeId { get; set; }
[Display(Name = "Tipo de Despesa")]
[Required]
public string ExpenseTipeName { get; set; }
public virtual ApplicationUser User { get; set; }
public string ApplicationUserId { get; set; }
I want to get all the ExpenseTipe related to the user that Create it, i think i need to do something in the linq query, to not get all the list of tipe of expenses, but just the expenses that have the same Id as the User but i dont know how to do it in the Linq query, here is my controller that fills the DropDown list.
public ActionResult Create([Bind(Include = "DespesaId,TipoDespesaId,DespesaDescricao,DespesaValor,TipoPagamentoId,Data,Comentario")] Despesa despesa)
{
if (ModelState.IsValid)
{
despesa.ApplicationUserId = User.Identity.GetUserId();
db.Despesas.Add(despesa);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.TipoDespesaId = new SelectList(db.TipoDespesas, "TipoDespesaId", "TipoDespesaNome", despesa.TipoDespesaId);
ViewBag.TipoPagamentoId = new SelectList(db.TipoPagamentos, "TipoPagamentoId", "TipoPagamentoNome", despesa.TipoPagamentoId);
return View(despesa);
}
I think i need a where condition in the viewBag but dont know how to do it :S
just add a where clause to your db.TipoDespesas.
db.TipoDespesas.where(x=> x.applicationUserid == UserId)

Entity Framework 1:1 relationship Code First

I'm struggling here. I've tried through data annotations and via the Fluent API and still not working correctly. Desperate for help now. Basically, I have two tables. A Company table and an Address Table. A company must have a head office address (which should live in the Address Table) and an Address must have a Company which is belongs too. I'm really struggling to set this up correctly.
I'll put the Code First Entities then show what I have already got.
[Table("Address")]
public class Address
{
[Key]
public long AddressId { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string Address4 { get; set; }
public string Address5 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Country { get; set; }
public string PostCode { get; set; }
public virtual Company Company { get; set; }
public DateTime? RemovedDate { get; set; }
public long? RemovedBy { get; set; }
}
[Table("Company")]
public class Company
{
[Key ]
public long CompanyId { get; set; }
public string Name { get; set; }
public string WebsiteUrl { get; set; }
public virtual Address Address { get; set; }
public User LeadUser { get; set; }
public DateTime ActiveSince { get; set; }
public DateTime? ActiveTill { get; set; }
public string VatRegistration { get; set; }
public string LicenseKey { get; set; }
public LicenseStatus LicenseStatus { get; set; }
public bool CanAgreementBeExtended { get; set; }
public string BillingEmail { get; set; }
public string PhoneNumber { get; set; }
public string MobileNumber { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public virtual ICollection<User> Users { get; set; }
public virtual ICollection<LicenseHistory> LicenseHistories { get; set; }
}
//Seeded data inserted as follows
var testCompany = new Company
{
ActiveSince = DateTime.UtcNow,
Name = "Test Company",
LeadUser = adminUser,
DateCreated = DateTime.UtcNow,
DateUpdated = DateTime.UtcNow,
BillingEmail = "admin#test.co.uk",
CanAgreementBeExtended = true,
LicenseStatus = LicenseStatus.PendingAgreement,
MobileNumber = "1234567890",
PhoneNumber = "1234567890",
VatRegistration = "1234567890"
};
context.Companies.AddOrUpdate(u => u.Name, testCompany);
var testAddress = new Address
{
Address1 = "Test Ltd",
Address2 = "1 Test Gardens",
Address3 = "Test Heath",
Address4 = string.Empty,
Address5 = string.Empty,
County = "Test",
Town = "Test",
Country = "United Kingdom",
PostCode = "TE5 T11",
Company = testCompany
};
context.Addresses.AddOrUpdate(u => new { u.AddressId }, testAddress);
testCompany.Address = testAddress;
context.Companies.AddOrUpdate(u => u.Name, testCompany);
//Fluent API set up as follows in the OnModelCreating
modelBuilder.Entity<Address>()
.HasRequired(ad => ad.Company)
.WithOptional(s => s.Address);
Can anyone spot what I'm doing wrong? I've been playing round with different combinations for the past few days and it just doesn't work. I just keep getting errors, the latest error based on the code above is...
A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'AddressId'.
Any ideas please?
You can't have a true one to one in SQL Server (see How do I create a real one-to-one relationship in SQL Server), but there is a workaround in EF where you make the primary key of the second entity also a foreign key:
// [Table("Company")] -- not needed unless different
public class Company
{
// [Key ] -- will be key by convention
public long CompanyId { get; set; }
...
public virtual Address Address { get; set; }
}
public class Address
{
[Key, ForeignKey("Company")]
public long AddressId { get; set; }
public string Address1 { get; set; }
...
public virtual Company Company { get; set; }
}
You can also do it with fluent code like:
modelBuilder.Entity<Company>()
.HasRequired(t => t.Address)
.WithRequiredPrincipal(t => t.Company);

EF code first update is not working for one to many relationship

The EF code first update is not working for one to many relationship
I have 2 entities
// Save
public class Person
{
public int Id { get; set; }
public string Name{ get; set; }
public virtual List<Email> Emails { get; set; }
}
public class Email
{
public int Id { get; set; }
public int PersonId { get; set; }
public virtual Person person { get; set; }
public string EmailAddress { get; set; }
}
EFContext context = new EFContext();
Person person;
Email email;
person = new Person();
person.Name = "Rocky";
person.Emails = new List<Email>();
email = new Email { EmailAddress = "rocky#frostbitefalls.com" };
person.Emails.Add(email);
email = new Email { EmailAddress = "rocky#squirrel.com" };
person.Emails.Add(email);
context.People.Add(person);
context.SaveChanges();
// Update
person = new Person();
person.Id=1;
person.Name = "Rocky Altered";
person.Emails = new List<Email>();
email = new Email {Id=1, EmailAddress = "Altered_rocky#frostbitefalls.com" };
person.Emails.Add(email);
email = new Email {Id=2, EmailAddress = "Altered_rocky#squirrel.com" };
person.Emails.Add(email);
UpdatePerson(person);
public bool UpdatePerson(Person entity)
{
var updatePerson = GetPersonById(entity.Id);
updatePerson.Name=entity.Name;
updatePerson.Emails=entity.Emails;
DataContext.Entry<Person>(updatePerson).State = EntityState.Modified;
DataContext.SaveChanges();
DataContext.Entry<Person>(updatePerson).Reload();
}
The person with 2 email addresses are saving properly but while updating the email address of the inserted person is not working.
You should do something like this:
public class Person
{
public int Id { get; set; }
public string Name{ get; set; }
public List<Email> Emails { get; set; }
}
public class Email
{
public int Id { get; set; } //This will generate PKey.
public virtual Person person { get; set; } //This will create the FKey.
public string EmailAddress { get; set; }
}
The problem you're having is that you need to apply a ForeignKeyAttribute to any FK you explicitly include:
public class Person
{
public int Id { get; set; }
public string Name{ get; set; }
public virtual List<Email> Emails { get; set; }
}
public class Email
{
public int Id { get; set; }
[ForeignKey("Person")]
public int PersonId { get; set; }
public virtual Person Person { get; set; }
public string EmailAddress { get; set; }
}
By applying that attribute you tell EF Migrations to use "PersonId" as the FK column name for the "Person" relationship. The rest should work as-is.

Resources