EF Core - Cannot add object with composite key - entity-framework

Alright, I'm trying to make a Wishlist containing user favorite items, however when I try to add them to the user, EF doesn't even try to INSERT, no action.
Here is my FavoriteProduct model
public class FavoriteProduct : BaseDeletableModel<int>
{
public string FashionNovaUserId { get; set; }
public FashionNovaUser FashionNovaUser { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
}
builder.Entity<FavoriteProduct>().HasKey(x => new { x.ProductId, x.FashionNovaUserId });
Here's my user model
public class FashionNovaUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<FavoriteProduct> FavoriteProducts { get; set; }
Then through my service layer I'm trying to add the favoriteProduct to user's list
var favoriteProduct = new FavoriteProduct
{
ProductId = id,
FashionNovaUserId = user.Id
};
user.FavoriteProducts.Add(favoriteProduct);
this.db.SaveChanges();
When I do that, there database table is not updated, nor it has any new entries.

Since FashionNovaUser and Product are many-to-many relationships, if you would like to add records of FavoriteProduct in join table, just use
var favoriteProduct = new FavoriteProduct
{
ProductId = id,
FashionNovaUserId = user.Id
};
this.db.Add(favoriteProduct);//or this.db.FavoriteProduct.Add(favoriteProduct)
this.db.SaveChanges();

Related

asp.net web api server data not syncing with database between BL

Hello I am new to servers and REST API and am trying to extract data from a dynamically created table and the data does not sync with the data in the database.
I have an sql database from which I extracted an entity database in asp.net web project.
This is an example for GET of one entity class (exists in database):
public class EmployeeBL
{
private FSProject1Entities db = new FSProject1Entities();
public List<Employee> GetEmployees(string fname, string lname, string depID)
{
return GetEmployeeSearchResult(fname, lname, depID);
}
}
And this is an example for a method from a class such as I created in order to combine data from 2 tables:
public class ShiftEmployeeDataBL
{
private FSProject1Entities db = new FSProject1Entities();
private List<ShiftEmployeeDataBL> GetEmployeeByShiftID(int id)
{
List<ShiftEmployeeDataBL> shiftEmpData = new List<ShiftEmployeeDataBL>();
foreach (Employee emp in db.Employee)
{//build list... }
return shiftEmpData;
}
My problem is that db.Employee via this GET request path (ShiftEmployeeData) is old data and via Employee GET request is good data (assuming the data was updated via Employee path).
And vice versa - it would appear that if I update Employee via ShiftEmployeeData class, it would appear as good data for ShiftEmployeeData class and not update for Employee.
I have APIcontrollers for both classes.
what is happening? I feel like I am missing something.
I tried closing cache options in browser.
update with code for elaboration:
entity Employee:
public partial class Employee
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int StartWorkYear { get; set; }
public int DepartmentID { get; set; }
}
employee update(auto generated by entity model code generation from db):
public void UpdateEmployee(int id, Employee employee)
{
Employee emp= db.Employee.Where(x => x.ID == id).First();
emp.FirstName = employee.FirstName;
emp.LastName = employee.LastName;
emp.StartWorkYear = employee.StartWorkYear;
emp.DepartmentID = employee.DepartmentID;
db.SaveChanges();
}
employeeshiftdata class (not a db table but still in the models folder):
public class EmployeeShiftData
{
public int ID { get; set; } //EmployeeID
public string FirstName { get; set; }
public string LastName { get; set; }
public int StartWorkYear { get; set; }
public string DepartmentName { get; set; }
public List<Shift> Shifts { get; set; }
}
employeeshift GET part of the controller:
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class EmployeeShiftDataController : ApiController
{
private static EmployeeShiftDataBL empShiftDataBL = new EmployeeShiftDataBL();
// GET: api/EmployeeShiftData
public IEnumerable<EmployeeShiftData> Get(string FirstName = "", string LastName = "", string Department = "")
{
return empShiftDataBL.GetAllEmployeeShiftData(FirstName, LastName, Department);
}
//...
}
Would need to see the code that interacts with the database, especially the code that makes the updates.
If the changes are written with Entity Framework, are the models themselves properly related with navigational properties?
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public List<EmployeeShift> EmployeeShifts { get; set; }
// etc.
}
public class EmployeeShift
{
public int Id { get; set; }
public Int EmployeeID { get; set; }
public Employee Employee { get; set; }
// etc.
}
If those are good, and both models are covered by Entity Framework's context tracking, then both should be updated.

update foreign key using entity framework

i am trying to update foreign key in a table named(Friendship).The foreign key is of the table named(FriendshipStatus) the problem is that all the values are updated except the foreign key. I m using code first approach.
Friendship Class
public class Friendship
{
public int Id { get; set; }
public User UserOne { get; set; }
public User UserTwo { get; set; }
public FriendshipStatus Status { get; set; }
public User ReqSB { get; set; }
public RelationType RelationType { get; set; }
public Relationship Relationship { get; set; }
public DateTime FriendshipDate { get; set; }
}
FriendshipStatus class
public class FriendshipStatus
{
public int Id { get; set; }
public string Name { get; set; }
}
Here is the code for update
using (context)
{
Friendship f = getFrienshipRecord(u1, u2); // get single record from db which is to be updated
if (f != null)
{
Friendship ff = new Friendship();
ff.Status = new FriendshipStatus() { Id = 2}; //actually wants to update this this field
ff.Id = f.Id;
ff.FriendshipDate = DateTime.Now;
context.Entry(ff).State = EntityState.Modified;
context.SaveChanges();
}
}
The above code changes datetime but it does not change foreign key.
This is the technique I use for updates that include a child. First, I like to expose the Foreign Key as part of the parent. If you name it FriendshipStatusId, EF will make the association automatically or you can add an annotation or fluent code if preferred:
public class Friendship
{
public int Id { get; set; }
public User UserOne { get; set; }
public User UserTwo { get; set; }
public int? FriendshipStatusId { get; set; } // optional FK
public FriendshipStatus Status { get; set; }
public User ReqSB { get; set; }
public RelationType RelationType { get; set; }
public Relationship Relationship { get; set; }
public DateTime FriendshipDate { get; set; }
}
Now you can do your update by simply fetching the entity (which puts it under tracking) and updating the FK:
using (context)
{
Friendship f = getFrienshipRecord(u1, u2); // get single record from db which is to be updated
if (f != null)
{
f.FriendshipDate = DateTime.Now;
f.FriendshipStatusId = 2;
context.SaveChanges();
}
}
Note that if you add the FK you may need to do a migration or regenerate your database because the EF default might be something like FriendshipStatus_Id.

Merge Key constraint with Entityframework

I am a .NEt student trying to build a simple pizza webbshop. I am using Entityframework to build the database. The errormessage I get is this:
The MERGE statement conflicted with the FOREIGN KEY constraint "FK_Products_Categories_CategoryID". The conflict occurred in database "TomasosPizzeria", table "dbo.Categories", column 'CategoryID'.
The statement has been terminated.
I have googled and tried to solve this pne alone by renaming the properties back and forth. Here are my classes:
public class Product
{
public int ID { get; set; }
public string ProductName { get; set; }
public int ProductPrice { get; set; }
public string Ingridients { get; set; }
//--
public List<OrderDetail> OrderDetails { get; set; }
[ForeignKey("Categories")]
public int CategoryID { get; set; }
public virtual Category Categories { get; set; }
}
public class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
List<Product> Products { get; set; }
}
I am using a DbInitializer to set som test values. I have had problems giving the product object a category with the corresponding value.
var categories = new Category[]
{
new Category{CategoryName="Pizza"},
new Category{CategoryName="Pasta"},
new Category{CategoryName="Sallad"},
};
var products = new Product[]
{
new Product{ProductName="Äcklig Calzone", Ingridients="Gamla tomater, möglig ost, trötta oliver, Unken skinka", ProductPrice=150},
new Product{ProductName="Italiensk skit", Ingridients="Proscutti, halvfärdig mozzarella, trötta oliver, skämd vattnig proscutti", ProductPrice=250},
new Product{ProductName="La bussola", Ingridients="Äckliga tomater, giftiga räkor, levande musslor, rutten skinka",CategoryID = 2,<--Here-- ProductPrice = 105 }
};
foreach (Product s in products)
{
context.Products.Add(s);
}
context.SaveChanges();
I am thankful for all the help I get. Please tell me if you wish to see any more of my code.
Solved it by giving CategoryID to the two other products.

why "Artists" table and linking table "ArtistAlbums" is not populate

I am trying to achieve many-to-many relationship with a linking table through EF code first approach.
The classes and context class are below,
public class Album
{
public Album()
{
Artists = new List<Artist>();
}
public int AlbumId { get; set; }
public string AlbumName { get; set; }
public List<Artist> Artists { get; set; }
}
public class Artist
{
public Artist()
{
Albums = new List<Album>();
}
public int ArtistId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public List<Album> Albums { get; set; }
}
public class ContextClass : DbContext
{
public DbSet<Album> Albums { get; set; }
public DbSet<Artist> Artists { get; set; }
}
While I am trying to add a album with two artists, then data populate only in "album" table, but no data available in other table "artist" and in linking table,please suggest?
using (var context = new ContextClass())
{
// add an album for two artists
var artist1 = new Artist { FirstName = "Tobby", LastName = "Keith" };
var artist2 = new Artist { FirstName = "Merle", LastName = "Haggard" };
var album = new Album { AlbumName = "Honkytonk University" };
artist1.Albums.Add(album);
artist2.Albums.Add(album);
context.Albums.Add(album);
context.SaveChanges();
}
Instead of
artist1.Albums.Add(album);
artist2.Albums.Add(album);
use
album.Artists.Add(artist1);
album.Artists.Add(artist2);
The issue is that only the 'album' object has been added to the context. The local 'album' object has no references to the Artist objects, so EF does not create the linked entities.
NOTE:
You could also replace
context.Albums.Add(album);
with
context.Artists.Add(artist1);
context.Artists.Add(artist2);
These local objects do have references, so EF will create the linked entity and the linking table entries.

Many to Many relationships with look up tables

public class Person {
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[ManyToMany(typeof(PersonColor), CascadeOperations = CascadeOperation.All)]
public List<Color> FavoriteColors { get; set; }
}
public class Color {
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
[ManyToMany(typeof(PersonColor))]
public List<Person> People { get; set; }
}
public class PersonColor {
[ForeignKey(typeof(Person))]
public int PersonId { get; set; }
[ForeignKey(typeof(Color))]
public int ColorId { get; set; }
}
...
var person = new Person() {
FirstName = "Adrian",
LastName = "Simbulan",
FavoriteColors = new List<Color>() {
new Color() {Name = "Red"},
new Color() {Name = "Green"}
}
};
await _db.InsertWithChildrenAsync(person);
Ok so i'm trying to establish a many to many relationship between Person and Color. The color table will be pre-populated with static data.
Now the problem is, whenever I execute the "InsertWithChildrenAsync" command, it always inserts new data into the Color lookup table. Is there a way to insert a Person record with selected colors with out affecting the Color table?
Try removing the write cascade operation from FavoriteColors attribute:
[ManyToMany(typeof(PersonColor), CascadeOperations = CascadeOperation.CascadeRead)]
public List<Color> FavoriteColors { get; set; }
This way the library won't perform recursive write operations on that table.
Another way without modifying the relationship is performing a two-step operation. First inserting the object and then updating the relationship:
await _db.InsertAsync(person);
await _db.UpdateWithChildrenAsync(person);
In both cases the the objects in the FavoriteColors list should already exist in the database and should have a valid primary key assigned. According to this, your sample code will never work because the identifier is 0 in all Color objects.