Querying database using Entity Framework not working as intended - c#

I have the current table, named Reviews: (I confirmed this directly in sql)
Id Name Summary Rating
1 Reviewer one Review one. 2.5
1 Reviewer two Review two. 1.5
1 Reviewer three Review three. 3.9
I'm trying to get all 3 reviews using id == 1 which is a foreign key but what happens is I get the first review 3 times:
Id Name Summary Rating
1 Reviewer one Review one. 2.5
1 Reviewer one Review one. 2.5
1 Reviewer one Review one. 2.5
Is there anything wrong with my code?
public List<Review> GetReviewModels(int restaurantId) //restaurantId is 1
{
List<Review> reviews = new List<Review>();
using (var db = new ReviewEntities())
{
reviews = db.Reviews.Where(e => e.id.Equals(restaurantId)).ToList();
}
return reviews;
}
And here's the review entity model:
public partial class Review
{
public int id { get; set; }
public string Username { get; set; }
public string Summary { get; set; }
public double Rating { get; set; }
public virtual Restaurant Restaurant { get; set; }
}

Your problem is in your Table/Model Your Model Should look Like:
public partial class Review
{
public int id { get; set; }
public string Username { get; set; }
public string Summary { get; set; }
public double Rating { get; set; }
public int RestaurantId {get;set;}
public virtual Restaurant Restaurant { get; set; }
}
And you will need to add this to your Sql:
ALTER TABLE Reviews
DROP CONSTRAINT /*Name of Id fied constraint here*/
-- on a side note, you may have to Drop foreign key depending on the way it is in the database
ALTER TABLE Reviews
ALTER COLUMN Id INT NOT NULL PRIMARY KEY IDENTITY(1,1)
ALTER TABLE Reviews
ADD COLUMN RestrauntId INT NOT NULL /*you can make this null if you need*/ FOREIGN KEY FK_Reviews_TO_Restraunt REFERENCES Restraunt(Id)

Changing
reviews = db.Reviews.Where(e => e.id.Equals(restaurantId)).ToList();
to
reviews = db.Reviews.AsNoTracking().Where(e => e.id.Equals(restaurantId)).ToList();
fixed the problem

You can try this in other way. As Reviews table references Restaurant table id so Restaurant entity model will be having List Reviews so in order to fetch all reviews for restaurant id 1 the goes is:
This is the Review Model class.
public partial class Review
{
public int id { get; set; }
public string Username { get; set; }
public string Summary { get; set; }
public double Rating { get; set; }
public virtual Restaurant Restaurant { get; set; }
}
This is the Restaurant Model class
public partial class Restaurant
{
public int Id{get;set;}
//Rest all other fields.
//Foreign key relationship/ Navigation property
public List<Reviews> Reviews {get;set;}
}
And the function code is as follows:
public List<Review> GetReviewModels(int restaurantId) //restaurantId is 1
{
List<Review> reviews = new List<Review>();
using (var db = new RestaurantEntity())
{
reviews = db.Restaurant.Where(e => e.id==restaurantId).Select(x=>
x.Reviews).FirstOrDefault();
}
return reviews;
}

Related

Navigation Property in EF Core is NULL

Can someone guide me on how to construct the proper property navigation on the below tables?
I have these tables in my database:
I then need to relate the Status table to get the status Name on every table
These are my model classes:
[Table("Companies")]
public class CompanyEntity
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Status_Id { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Updated_Date { get; set; }
[ForeignKey("Status_Id")]
public Status Status { get; set; }
}
[Table("Customers")]
public class CustomerEntity
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Status_Id { get; set; }
}
[Table("Status")]
public class Status
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public Company Company { get; set; }
}
My goal is to when I get all the Companies or Customers using DBContext e.g. var companies = _dbContext.Companies.ToList(). I want to get the status of every record for Companies and Customers. I'm not so sure how to construct the navigation property properly for the said models.
TIA!
Update #1
After following the below suggestion, yes the Status is not NULL anymore. But, it gets the wrong status id. Instead of using the Status_Id, it uses the Id of the Company. Please see below snippets. The status of the said company is 6.
But if you notice on the 2nd snip, the status is 3 which is the Id of the Company.
I also have this code in OnModelCreating.
modelBuilder.Entity<Company>()
.HasOne<Status>()
.WithMany()
.HasForeignKey(p => p.Status_Id);
This is the reason why I get that behavior. But if I removed this, the Status property is gets NULL.
Update #2
Just fixed my issue. I need to change the Company property from public Company Company { get;set; } to public List Companies { get;set; }. Then add the suggested answer Include`.
[Table("Status")]
public class Status
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public List<Company> Companies { get; set; }
}
You have to add the .Include() method to join your status table in your result like so:
_dbContext.Companies.Include(c => c.Status).ToList()

1 to many relationship isn't resulting in what I'd expect

In a scenario where a product can have many categories I'm trying to create this using code-first, I have a Product model which has a collection of Category like so:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Category> Categories { get; set; }
}
My Category looks like:
public class Category
{
public Category(CategoryEnum #enum)
{
Id = (int)#enum;
Name = #enum.ToString();
}
public Category() { }
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Name { get; set; }
public static implicit operator Category(CategoryEnum #enum) => new Category(#enum);
public static implicit operator CategoryEnum(Category category) => (CategoryEnum)category.Id;
}
Creating a migration then updating the database doesn't create a new table for this to join the 2 (Product and Category) together. I'd expect a new table with a ProductId and CategoryId but this isn't the case. Instead, it just creates a ProductId in the Category table?
How do I make EF create a table which joins the 2 together without having to create a new DbSet<T>
That is how it's supposed to be.
Example:
Product 1 Chicken
Categorie 1 Meat idProduct = 1
Categorie 2 Healthy idProduct = 1
etc...
You don't need another table for a relation one to many. The table is only usefull for many to many

Add an Entity object with its Related Entity based on primary keys

I have an entity like this:
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string FullText { get; set; }
public string Tags { get; set; }
public virtual Category Category { get; set; }
}
This entity has relations to Category:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual IList<Post> Articles { get; set; }
}
Now, when inserting data into the Post table, I use this code:
var post = new Post
{
Category = _categoryService.FindById(model.CategoryId),
FullText = model.FullText,
Tags = model.Tags,
Title = model.Title,
};
_articsleService.Save(post);
This code works fine, but it has 1 fetching data form database. In entity objects that has more than 3 relations, I think this way not so good. Therefore, another way can be like this:
var post = new Post
{
Category = new Category { Id = model.CategoryId },
FullText = model.FullText,
Tags = model.Tags,
Title = model.Title,
};
_articsleService.Save(post);
But, when the code is run, I get this exception:
Cannot insert explicit value for identity column in table 'Categories' when IDENTITY_INSERT is set to OFF.
Is there any best solution for this problem?
Add to your post model the FK to CategoryId
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string FullText { get; set; }
public string Tags { get; set; }
public virtual Category Category { get; set; }
public int CategoryId { get; set; }
}
Then just add a new post after updating your db model.
var post = new Post
{
CategoryId = model.CategoryId,
FullText = model.FullText,
Tags = model.Tags,
Title = model.Title,
};
_articsleService.Save(post);
That's it, EF will do the rest for you.
Your current approach leads to creating a new Category which does not work bc the same primary key already exists and inserting into an identity column is not enabled by default. This is how change-tracking from EF works. EF creates a proxy from each database row as an entity in your code and tracks this entity during application lifetime.
You can read more about it here.

Entity Framework error message DbUpdateException

As part of an assignment, I must create a web app using Entity Framework. I am following the tutorial at https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application.
There are four tables: Branch, Department, Employee and Title.
After creating a method to seed the data I have run the application in debugging mode and got the following error message:
System.Data.Entity.Infrastructure.DbUpdateException: ‘An error occurred while updating the entries. See the inner exception for details.’ SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.Employee_dbo.Branch_BranchId". The conflict occurred in database “HumanResourcesWebApp1”, table “dbo.Branch”,column ‘ID’. The statement has been terminated.
I have researched this message but I am not following the answers which I have found. I would be grateful for some direction. I am also adding the structure of the classes if it helps. I understand that the issue is between the primary key of the Branch table when seen as a foreign key by the Employee table but I do not know where to make changes.
Branch:
public int ID { get; set; }
public string Address { get; set; }
public int DepartmentID { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
Department:
public int ID { get; set; }
public string DepartmentName { get; set; }
public string DepartmentFunction { get; set; }
public virtual ICollection<Branch> Branches { get; set; }
Employee:
public int ID { get; set; }
public string FirstName { get; set; }
public string SecondName { get; set; }
public double Salary { get; set; }
public DateTime StartingDate { get; set; }
public int BranchId { get; set; }
public int TitleId { get; set; }
Title:
public int ID { get; set; }
public string TitleName { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
Thanks in advance
You're attempting to save employee details that reference a branch that doesn't exist. This is either because you haven't set the branch id at all, or you have set it to a number that is not present in the branch table Set the employees branch id to a branch that already exists. If no branches exist, create one. You should be able to create a branch and an employee simultaneously in code so long as the employee correctly refers to the branch. Entity framework should save the branch first so that it exists at the point it comes to save the employee

Adding Extra Column to join table

I currently have an employee model
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<StateLicenseType> Licenses { get; set; }
and a License Type Model
public class StateLicenseType
{
public int StateLicenseTypeId { get; set; }
public string State { get; set; }
public string LicenseName { get; set; }
public virtual Employee Employee { get; set; }
}
This relationship can be one to many, but I also need to add some information to the license when saved. I need to be able to store the employees unique license number and have not been able to find out how to do this while searching around. Is there a way to have Entity Framework add a column to a join table and then even if I have to, update it myself?
Is there a better/different way to model this relationship with EF?
In an old DB the table was created like this,
CREATE TABLE `nmlsstatelicenses` ( `peopleid` int(11) DEFAULT NULL, `statelicensetypeid` int(11) DEFAULT NULL, `licensenumber` varchar(25) DEFAULT NULL)
You need to create a third entity which will be a linking entity (like a linking table in many-to-many relationships in database. Here is an example: many-to-many relationships with additional information.
So you would have the following entities in your model:
public Employee
{
public string EmployeeId { get;set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<LicenseRegistration> RegisteredLicenses { get; set; }
}
public LicenseType
{
public int StateLicenseTypeId { get; set; }
public string State { get; set; }
public string LicenseName { get; set; }
public virtual ICollection<LicenseRegistration> RegisteredLicenses { get; set; }
}
public LicenseRegistration
{
//properties for the additional information go here
/////////////////////////////////////////////////////
public int EmployeeId {get;set;}
[ForeignKey("EmployeeId")]
public Employee Employee {get;set;}
public int LicenseTypeId {get;set;}
[ForeignKey("LicenseTypeId")]
public LicenseType {get;set;}
}
Then, in your DBContext file, you will need to define 1-to-many relationship between Employee and LicenseRegistration, and between LicenseType and LicenseRegistration.
Hope this helps!
UPDATE
Here is how you would set up the relationships:
modelbuilder.Entity<LicenseRegistration>()
.HasRequired(lr => lr.LicenseType)
.WithMany(lt => lt.RegisteredLicenses)
.HasForeignKey(lr => lr.LicenseTypeId);
modelbuilder.Entity<LicenseRegistration>()
.HasRequired(lr => lr.Employee)
.WithMany(e => e.RegisteredLicenses)
.HasForeignKey(lr => lr.EmployeeId);

Categories

Resources