EntityFramework changing my query - EntityCommandExecutionException - c#

I'm getting a 'EntityCommandExecutionException' and
An error occurred while executing the command definition. See the inner exception for details.
with an inner message of
Invalid column name 'Department_ID'
This seems to be the query executed from this line of code:
List<Employee> _employees = employeeContext.Employees.ToList();
SELECT [Extent1].[EmployeeID] AS [EmployeeID],
[Extent1].[Name] AS [Name],
[Extent1].[Gender] AS [Gender],
[Extent1].[City] AS [City],
[Extent1].[DepartmentID] AS [DepartmentID],
[Extent1].[DateOfBirth] AS [DateOfBirth],
[Extent1].[Department_ID] AS [Department_ID]
FROM [dbo].[tblEmployee] AS [Extent1]
This is wrong considering there is no Department_ID, I have no idea where it is getting this from. This is the Employee class model:
[Table("tblEmployee")]
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public int DepartmentID { get; set; }
public DateTime DateOfBirth { get; set; }
}
[Table("tblDepartment")]
public class Department
{
public Int16 ID { get; set; }
public string Name { get; set; }
public List<Employee> Employees { get; set; }
}
Not sure what to do. Any ideas?

The Department_ID is coming by virtue of the relationship in your Department class. You have a List Employees there which automatically assumes a column called Department_ID in your Employee table.
What you need to do is add a virtual property called Department in your Employee table instead of adding the DepartmentID
[Table("tblEmployee")]
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public virtual Department Department { get; set; }
public DateTime DateOfBirth { get; set; }
}
If you need to maintain the column name as DepartmentID or you need access to the property DepartmentID in code, then you need to use the ForeignKey attribute as shown below:
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public int DepartmentID { get; set; }
[ForeignKey("DepartmentID")]
public virtual Department Department { get; set; }
public DateTime DateOfBirth { get; set; }
}
I would also recommend that you maintain the List as virtual.

Related

how to update the model class recipe?

I have two model classes Category and Recipe and their relationship in one to many. I want to Edit the Recipe and also change the category that the recipe belongs to.Thanks in advance.
public class CookContext : DbContext
{
public CookContext(): base("cookContext")
{
}
public DbSet<Recipe> Recipes { get; set; }
public DbSet<Category> Categories { get; set; }
}
public class Category
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Recipe> Recipes { get; set; }
}
public class Recipe
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Ingridients { get; set; }
public string Image { get; set; }
public Category category { get; set; }
}
[HttpPost]
[ValidateInput(false)]
public ActionResult EditRecipe(Recipe recipe, int? categoryName)
{
var category = context.Categories.Where(c => c.Id ==
(int)categoryName).FirstOrDefault();
context.Entry(recipe).State = EntityState.Modified;
recipe.category = category;
context.SaveChanges();
}
The error messages i get are:
1.
[DbUpdateException: An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types.
2.
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.
Try by adding the field CategoryId to your Recipe class, also, the category property should begin with a capital "C".
The collection property should be marked virtual if you want the data to be lazy loaded (only loaded when needed) otherwise, you may load all recipes for a given category every time you make a query:
public class Recipe
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Ingridients { get; set; }
public string Image { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
public class Category
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Recipe> Recipes { get; set; }
}
If it doesn't work try by setting up the ForeignKey attribute:
public class Recipe
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Ingredients { get; set; }
public string Image { get; set; }
[ForeignKey("Category")]
public int CategoryId { get; set; }
public Category Category { get; set; }
}
public class Category
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Recipe> Recipes { get; set; }
}

Entity Framework Code First Renaming Columns/Keys

I have an Employee table that links employees to their contact info. I have it set up like so:
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
[ForeignKey("HomePhoneId")]
public virtual PhoneNumber HomePhone { get; set; }
[ForeignKey("WorkPhoneId")]
public virtual PhoneNumber WorkPhone { get; set; }
[ForeignKey("CellPhoneId")]
public virtual PhoneNumber CellPhone { get; set; }
When I try to load employees from the database, however, it automatically renames the columns, completely overriding the attributes:
Invalid column name 'PhoneNumber_Id'.
Invalid column name 'PhoneNumber_Id1'.
Invalid column name 'PhoneNumber_Id2'.
Invalid column name 'Address_Id'.
Why is it doing this?
As stated by #mcbowes, it is hard to tell without seeing the rest of your Employee class, but most likely you are missing the following in your class:
public int AddressId { get; set; }
public int HomePhoneId { get; set; }
public int WorkPhoneId { get; set; }
public int CellPhoneId { get; set; }
The IDs were all properly specified for each navigation property. It seems the problem had to do with the navigation properties on each PhoneNumber and Address object that linked back to the Employee. I don't need them for now, so removing those navigation properties corrected the issue.
As an expansion on #peinearydevelopment set up your PhoneNumber:
public class PhoneNumber
{
public PhoneNumber(string name, int areaCode, string number)
{
Name = name;
AreaCode = areaCode;
Number = number;
}
public int ID { get; set; }
public string Name { get; set; }
public int AreaCode { get; set; }
public string Number { get; set; }
}
}
Set up your Employee:
public class Person
{
public Person(string first, string last, PhoneNumber home, PhoneNumber cell)
{
First = first;
Last = last;
HomeNumber = home;
CellNumber = cell;
}
public int ID { get; set; }
public string First { get; set; }
public string Last { get; set; }
public int HomePhone_ID { get; set; }
public int CellNumber_ID { get; set; }
public virtual PhoneNumber HomeNumber { get; set; }
public virtual PhoneNumber CellNumber { get; set; }
}
}
And your Context
public class PersonContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<PhoneNumber> PhoneNumbers { get; set; }
}
As you can see, relationships are maintained, but you do need to explicitly tell your application which fields hold the identifiers, not just which tables have the relationships.

2 different models - how to connect them in MVC 5?

For my web app project, I have 2 models that are related to each other. Model Department is related to Model Employee. Each employee is assigned one department, while each department can have many employees. In the Departments view, I have an "Add new employee" option. When the add new employee button is clicked, a modal popup comes up which shows the Employees/Create view. My problem is I don't know how to link employee to department so that the employee automatically gets added to the department view next to the right department.
Right now, my Employee/Create view just gives the user a dropdown list of Departments to link the employee to. I want the employee to be automatically linked to the department when the "add employee" option is shown in the Departments view.
Here's the Department model:
public class Department
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string BuildingLocation { get; set; }
public string DirectLine { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
Here's the Employee model:
public class Employee
{
[Key]
public int EmployeeID { get; set; }
[ForeignKey("Department")]
public int DepartmentID { get; set; }
public string EmployeeFirstName { get; set; }
public string EmployeePosition { get; set; }
public string EmployeePhoneNo { get; set; }
public string EmployeeEmail { get; set; }
public virtual Department Department { get; set; }
}
I think you can create a EmployeeViewModel. For example:
public class Employee
{
public int EmployeeID { get; set; }
public int DepartmentID { get; set; }
public string EmployeeFirstName { get; set; }
public string EmployeePosition { get; set; }
public string EmployeePhoneNo { get; set; }
public string EmployeeEmail { get; set; }
public SelectListItem DepartmentList { get; set; }
}
When you click button add new employee, just set DepartmentId = DepartmentId that you selected. Or you can let the user changes Deparment.
You can create a ViewModel like this. Whenever you want to show employee details in the view then just map your data to this view model along with "DepartmentID" and "DepartmentName". To get "DepartmentName" you can join with department table and get department name.
public class EmployeeViewModel
{
public int EmployeeID { get; set; }
public string EmployeeFirstName { get; set; }
public string EmployeePosition { get; set; }
public string EmployeePhoneNo { get; set; }
public string EmployeeEmail { get; set; }
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
public virtual Department Department { get; set; }
}
To Get Department Name you can join with Employe table like this. (Note that I've used EntityFramework here to retrieve data)
var employeeList = from e in dbContext.Employees
join d in dbContext.Departments on e.DepartmentID equals d.DepartmentID
select new EmployeeViewModel
{
EmployeeID = e.EmployeeID,
EmployeeFirstName = e.EmployeeFirstName,
EmployeePosition = e.EmployeePosition,
EmployeePhoneNo = e.EmployeePhoneNo,
EmployeeEmail = e.EmployeeEmail,
EmployeePhoneNo = e.Name,
DepartmentID = e.DepartmentID,
DepartmentName = d.DepartmentName
};

Entity Framework 6 table with many foreign keys each pointing to different tables

I have Country, City, Region and "Account Address" tables.
I want to create foreign key columns in "Account Address" pointing to Country, City, Region tables.
I have this code but it throws an error on creating database
The property \u0027Account_Id\u0027 cannot be configured as a
navigation property. The property must be a valid entity type and the
property should have a non-abstract getter and setter. For collection
properties the type must implement
After New Edit
public class Cities
{
[Key]
public int City_Id { get; set; }
public string City_name { get; set; }
public int Country_Id { get; set; }
[ForeignKey("Country_Id")]
public Countries countries { get; set; }
}
public class Region
{
[Key]
public int Region_Id { get; set; }
public string Region_name { get; set; }
public int City_Id { get; set; }
[ForeignKey("City_Id")]
public Countries countries { get; set; }
}
public class Accounts
{
[Key]
public int Account_Id { get; set; }
public string Fullname { get; set; }
public string Email { get; set; }
public string password { get; set; }
public int Cell_phone { get; set; }
public string Role { get; set; }
public int? estate_office_Id { get; set; }
[ForeignKey("estate_office_Id")]
public Estate_office estate_office { get; set; }
public List<Ads> ads { get; set; }
}
public class Account_address
{
[Key]
public int Id { get; set; }
[ForeignKey("Account_Id"), Column(Order = 0)]
public int Account_Id { get; set; }
[ForeignKey("Country_Id"), Column(Order = 1)]
public int Country_Id { get; set; }
[ForeignKey("City_Id"), Column(Order = 2)]
public int City_Id { get; set; }
[ForeignKey("Region_Id"), Column(Order = 3)]
public int Region_Id { get; set; }
public Accounts accounts { get; set; }
public Countries countries { get; set; }
public Cities cities { get; set; }
public Region region { get; set; }
}
You need to define public properties as shown below on the Account_address class.Then only EF will know how to map those navigation properties correctly.
public class Account_address
{
......
......
public Accounts accounts { get; set; } //like this
public Countries countries { get; set; } //like this
public Cities cities { get; set; } //like this
public Region region { get; set; } //like this
}
Update :
Hence you're not using singular naming convention for the classes,you have encountered this issue.Either you have to change the name of classes as singular or need to change the navigational property names a shown below.You have to do this for all the places.Here I have shown only for the Accounts class related navigational property.
[ForeignKey("Accounts_Id"), Column(Order = 0)]
public int Accounts_Id { get; set; }
My Advice is to follow the basic naming conventions.Then you can avoid lot of above kind of weird errors.

Save complexa data using entity framework

Hi every one I want to save complex data using Entity Framework and C#. I have 2 classes Product and Order defined as follows
Product Class
public class Product
{
[Key]
public int Id { get; set; }
public string SKU_Code { get; set; }
public string Product_Name { get; set; }
public string Quantity { get; set; }
public string Price { get; set; }
public string Image { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
Order Class
public class Order
{
[Key]
public long ID { get; set; }
public string Order_Id { get; set; }
public string Payment_Type { get; set; }
public string Customer_Name { get; set; }
public string Shipping_Address { get; set; }
public DateTime Order_Date { get; set; }
public DateTime Modified_Date { get; set; }
public bool Flag { get; set; }
public List<Product> ProductDetails { get; set; }
}
And I want to save data Order details and my piece of code is as follows.
public Order Add(Order odrerDetails)
{
using (var context = new EcommerceDBContext())
{
var MyOrder_Id = Helper.Random(7); //Generate random orderID from my class
foreach (var detail in odrerDetails.ProductDetails)
{
odrerDetails.Order_Id = MyOrder_Id;
odrerDetails.Quantity = Convert.ToInt32(detail.Quantity);
odrerDetails.Amount = Convert.ToDouble(detail.Price);
//Other Details
context.objOrderListing.Add(odrerDetails);
}
context.SaveChanges();
return odrerDetails;
}
}
This gives me perfect data but when it comes to context.SaveChanges(); it return's me error.
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types.
To me you domain model seems all wrong. The order should just be used for grouping, its a typical e-commerce scenario.
When you get a receipt of your purchases, you get one receipt with every Item and price listed next to it. Its considered as one order of multiple things, not multiple orders of multiple things.
Reading your last comment, you cant have multiple orders with the same order id. Try to understand the domain first before trying to solve it with code. Also,you have no notion of a Customer with an Order.
public class Product
{
[Key]
public int Id { get; set; }
public string SKU_Code { get; set; }
public string Product_Name { get; set; }
public string Price { get; set; }
public string Image { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
public class Order
{
[Key]
public long ID { get; set; }
public string Order_Id { get; set; }
public string Payment_Type { get; set; }
public string Customer_Name { get; set; }
public string Shipping_Address { get; set; }
public DateTime Order_Date { get; set; }
public DateTime Modified_Date { get; set; }
public bool Flag { get; set; }
public List<OrderLineItem> Items { get; set; }
}
public class OrderLineItem
{
[Key]
public long ID { get; set; }
public long Order_Id { get; set; }
public long Product_Id {get; set;}
public int Quantity {get; set;}
}

Categories

Resources