Having problem in displaying relational properties b/w two tables having one(company) to many(package_master) relationship
Action
public ViewResult Index()
{
var companies = db.companies.Include(c => c.aspnet_Users)
.Include(c=>c.package_master);
return View(companies.ToList());
}
EntitySet
public partial class company
{
public company()
{
this.package_master = new HashSet<package_master>();
}
public int company_id { get; set; }
public string name { get; set; }
public string address { get; set; }
public string phone { get; set; }
public string fax { get; set; }
public Nullable<System.Guid> sen_sup { get; set; }
public virtual aspnet_Users aspnet_Users { get; set; }
public virtual ICollection<package_master> package_master { get; set; }
}
When I type Model.aspnet_Users.property1 everything works fine(intellisense) but now I also want to diaplay properties from packege_master(no intellisense)(foreign key table=package_master having client_id as foreign key, public key table=company having company_id as primary key)
package_master is a collection. You cannot access member properties of package_master entities directly like: Model.package_master.XXX. You must iterate the collection to get access to entities.
Related
I have created one asp.net mvc web api using Entity framework model, Which can update Single table in Single request. What i want is to update two tables(Having foreign key relationship) in single POST Request.
How I can achieve this?
What I have Done:-
1.Created Two Table tblEmployeeRecord & tblCountryName in sql server with EmployeeId as a primary key & foreign key respectively.
2.Employee table Model:-
public partial class tblEmployeeRecord
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string userName { get; set; }
public string userRole { get; set; }
}
3.Country Name table Model:-
public partial class tblCountryName
{
public int CountryId { get; set; }
public int EmployeeId { get; set; }
public string Country_Name { get; set; }
}
4.Created wrapper Model as follow:-
public class UserAndCountry
{
public tblEmployeeRecord UserRecord { get; set; }
public tblCountryName CountryRecord { get; set; }
}
5.ActionResult Method in Controller Which handles post request:-
[ResponseType(typeof(UserAndCountry))]
public IHttpActionResult PosttblEmployeeRecord(UserAndCountry tblEmployeeRecord)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.tblCountryNames.Add(tblEmployeeRecord.CountryRecord);
db.tblEmployeeRecords.Add(tblEmployeeRecord.UserRecord);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = tblEmployeeRecord.UserRecord.EmployeeId }, tblEmployeeRecord);
}
6.Note:-What is Happening:- When I don't define foreign key relationship in SQL Server between these two table, I am able to update both table but when i define foreign key relationship I am not able to update these tables What will be my request object in that case, Where I am going wrong?
7.My Current Request object:-
{
"CountryRecord":
{
"Country_Name": "AP"
},
"UserRecord":
{
"Name": "Test User",
"userName": "Test.User#mail.com",
"userRole": "Hr"
}
}
The power of entity framework is the navigation properties for relationships. So say your models were:
public partial class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string userName { get; set; }
public string userRole { get; set; }
// Foreign Key
public int CountryId { get; set; }
// Navigation Property
public virtual Country EmployeeCountry
}
public partial class Country
{
public int CountryId { get; set; }
public string Country_Name { get; set; }
}
Now your update becomes:
var employeeRecord = tblEmployeeRecord.UserRecord;
// add the country. EF will make the relationship automagically
employeeRecord.EmployeeCountry = tblEmployeeRecord.CountryRecord;
db.Employees.Add(employeeRecord);
db.SaveChanges();
I have a table in my EF model that is not creating within the database on access.
The table name is "sites" and is linked to a parent table by the use of a foreign key called "CompanyId".
I am attmempting to list all the sites that belong to a specific company (the company table is linked to the ApplicationUser)
I would expect that when i call the database for a list of the sites that it will be created. However i just receive an error that states the table does not exist
My model for the two tables is as follow
public class Company
{
[Key]
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string PostCode { get; set; }
public string County { get; set; }
public string Country { get; set; }
public string TelephoneNumber { get; set; }
public string Email { get; set; }
public virtual IQueryable<Site> Sites { get; set; }
}
public class Site
{
[Key]
public int SiteId { get; set; }
public int CompanyId { get; set; }
public string SiteName { get; set; }
public string Url { get; set; }
}
and my controller
public ActionResult Index()
{
//get the user details
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var currentuser = manager.FindById(User.Identity.GetUserId());
// search
var company = currentuser.Companies;
var sites = company.Sites;
if (sites == null)
{
sites = db.Sites.Where(c => c.CompanyId == company.CompanyId);
return View(sites.ToList());
}
return View(company.Sites.ToList());
}
You can see which table is created in your database using Database Manager?
Try
1: Change
public virtual IQueryable<Site> Sites { get; set; }
for
public virtual ICollection<Site> Sites { get; set; }
2: Add property to your site class
public Company Company { get; set; }
Did you create a migration for the change? If not the issue the "Add-Migration whateverYouWant" command in your package manager console.
Do you have automatic migrations enabled? If not then you have to auth the command "update-database" in your package manager console.
Look into your Configuration.cs file under the Migrations folder
and check the Configuration constructor. There should be a property called "AutomaticMigrationsEnabled" set to true in order for this to do what you are expecting.
I am new to Entity Framework and Asp.NET, and therefore, struggling with creating database relationships within the Entity Framework.
I have two SQLite tables (Ticket and User) and have setup my entity models as follows:
public class Users
{
[ForeignKey("id")]
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public int? assigned_to { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
public virtual Users Users { get; set; }
}
I am trying to use Entity Framework 7 to export an IEnumerable<Tickets> that includes the User assigned to each Ticket.
I have tried to create my model relationship in MyDBContext as a single User can have multiple Tickets, and also has a foreign key associated in my Sqlite database (Tickets.assigned_to = User.id):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne(e => e.Users)
.HasForeignKey(p => p.assigned_to);
}
My result ends up with Ticket data being exported, but against every ticket I see a null value for User:
[{"id":10002,...,"Users":null}]
When I use .Include() within my Repository to include each User like this:
public IEnumerable<Tickets> GetAll()
{
return _db.Tickets.Include(t => t.Users).ToList();
}
It results in the error
HTTP Error 502.3 - Bad Gateway
The specified CGI application encountered an error and the server terminated the process.
What I'm trying to retrieve is data that looks like:
{"Ticket";[{"id":10002,..."status":"closed"}],"Users":[{"id":"1"..."email":"johndoe#someplace.com"}]}
I know it probably has something to do with my relationship model, but I cannot work out what I am doing wrong.
First you should really derive your Users from IdentityUser. It helps when trying to wire up the relationship, but I will give you the answer based on your current models. Your ForeignKey property should be on the child entity. By naming conventions, which is what EF uses by default, your public Users Users works better if you put a public int UsersId. Then essentially what EF will do is from your public Users Users it will go to the Users table. Then it looks for the ForeignKey which is set to Id, so now we are in the Users Table looking at the id property. Then it looks for the naming convention UsersId and if it sees it, it will set that property to the value that it saw from the Users Table Id column.
Try using this
public class Users
{
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
[ForeignKey("Id")]
public int UsersId { get; set; }
public virtual Users Users { get; set; }
}
and for your Fluent API configuring
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne();
}
Now all that does is create the relationship. In order to view the specific items you want to view, use a ViewModel. So, pull the two lists you want from where you want. Then use logic to separate the list how you want them to display.
public class UsersViewModel()
{
public UsersViewModel(Users user, List<Tickets> tickets)
{
this.first_name = user.first_name;
this.last_name = user.last_name;
this.email = user.email;
this.Tickets = new List<Tickets>();
foreach(var ticket in tickets)
{
if(ticket.UserId == user.Id)
{
this.Tickets.Add(ticket)
}
}
}
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public List<Tickets> Tickets { get; set;}
}
then in your controller make your list
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var ticketsList = _repository.Tickets.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
or use a Linq query
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var ticketsList = from x in _repository.Tickets where x.UserId.Equals(user.Id) select x;
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
then at the top of your view you should have
#model IEnumerable<UsersViewModel>
public partial class User {
public int Id { get; set; }
public Nullable<int> InvoiceAddress_Id { get; set; }
public Nullable<int> MailAddress_Id { get; set; }
public virtual Address Address { get; set; }
public virtual Address Address1 { get; set; }
}
When I try to retrieve user using Linq and Entity framework, I get;
Invalid column name 'Address_Id1'.
Invalid column name 'Address1_Id1'.
Invalid column name 'Address_Id'.
Invalid column name 'Address_Id1'.
I have no idea why it's coming up like that and doing search for any of these columns in the solution gives nothing! I have a feeling it has something to do with foreign keys.
public partial class Address
{
public Address()
{
this.User = new HashSet<User>();
this.User1 = new HashSet<User>();
}
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public virtual ICollection<Customer> User { get; set; }
public virtual ICollection<Customer> User1 { get; set; }
}
Here is how I'm using entity framework:
CustomDbContext db = new CustomDbContext ();
var user = db.User.First(a => a.Id != 0);
Here's the updated code:
public partial class User
{
public int Id { get; set; }
public Nullable<int> InvoiceAddress_Id { get; set; }
public Nullable<int> MailAddress_Id { get; set; }
public virtual Address InvoiceAddress_ { get; set; }
public virtual Address MailAddress_ { get; set; }
}
Here's the error:
Invalid column name 'Address_Id'.
Invalid column name 'Address_Id1'.
The problem is quite clear: nor your code (attributes, fluent API), neither the EF conventions are configuring the FKs.
If you want to use conventions, you have to adjust the names of the properties and the foreign keys, so that they can be configured. Where you have:
public Nullable<int> InvoiceAddress_Id { get; set; }
public virtual Address Address { get; set; }
You should have:
public Nullable<int> InvoiceAddressId { get; set; }
public virtual Address InvoiceAddress { get; set; }
Note that the FK name is the navigation property name + "Id"
Other option is to implement OnModelCreating of your DbContext and configure the FKs using the fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasOptional(u => u.Address)
.WithMany();
.HasForeingKey(a => a.InvoiceAddres_Id);
}
Or use the [ForeignKey("")] attribute:
The annotation may be placed on the foreign key property and specify the associated navigation property name, or placed on a navigation property and specify the associated foreign key name
I.e.
[ForeignKey("Address")]
public Nullable<int> InvoiceAddress_Id { get; set; }
or
[ForeignKey("InvoiceAddress_Id")]
public virtual Address Address { get; set; }
I am a MVC newbie so go easy on me please.
I am getting two errors when I try to add a migration. They are as follows:
EntityType 'Icon' has no key defined. Define the key for this EntityType.
EntityType: EntitySet 'Icons' is based on type 'Icon' that has no keys defined.
I am including the Icon inside another model, like so:
public class Icon
{
public string IconName { get; set; }
public string IconColor { get; set; }
public int BackgroundXPos { get; set; }
public int BackgroundYPos { get; set; }
public string IconColorHover { get; set; }
public int BackgroundHoverXPos { get; set; }
public int BackgroundHoverYPos { get; set; }
}
public class GalleryThumbnail : CSSBoxModel
{
[DisplayName("Thumbnail Image Outline Color")]
public string ThumbnailImageOutlineColor { get; set; }
[DisplayName("Thumbnail Menu Font")]
public CSSFont ThumbnailMenuFont { get; set; }
[DisplayName("Thumbnail Icon Color")]
public Icon ThumbnailIconColor { get; set; }
}
How is this Address class below any different which is working:
public class Address
{
public String Adress1 { get; set; }
public String Adress2 { get; set; }
public String Adress3 { get; set; }
public String City { get; set; }
public String County { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public String Country { get; set; }
}
[Table("UserProfile")] //Could be PP empolyee, Subscriber or Subscriber's customer
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public bool? Gender { get; set; }
public Address Address { get; set; } //billing address
public Address ShipAddress { get; set; }
}
I did not add a key in either my Icon or Address class because I have no intention of storing specific data in my DB. They are merely to be used inside other classes. So wy is one neededing an ID and the other is not?
I have not created public DbSet Icons { get; set; } in my DB Context either.
Also can you tell me what it is called when you use a class inside another ( or instance of class inside a class as in these examples ) ?
Much appreciated!
Since the address entity has no key defined it the Entity Framework assumes it's a complex property, and your UserProfile table will be rendered with columns named Addres_Address1, Address_Address2, Address_Address3, Address_City, and so on...
Even though you haven't declared an EntitySetIcons DbSet on your context class, it's still being added implicitly because one of your other classes somewhere has an ICollection or IEnumerable property defined.
More info on Code Conventions here:
http://msdn.microsoft.com/en-us/data/jj679962.aspx
So, either decorate the collections as NotMapped like #Kamyar said or simply remove the references from any class already declared as a DbSet.
you can use [NotMapped] attribute in System.ComponentModel.DataAnnotations.Schema namespace in EntityFramework.dll:
using System.ComponentModel.DataAnnotations.Schema;
...
[NotMapped]
public Address Address { get; set; } //billing address
[NotMapped]
public Address ShipAddress { get; set; }
Regarding the naming, AFAIK these are called public properties as well.