why "Artists" table and linking table "ArtistAlbums" is not populate - entity-framework

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.

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.

How to find a holder of a property

In the following example in Entity Framework, how to find the author of a specified book using linq:
public class Author
{
public int Id { get; set; }
public string AuthorName { get; set; }
public ICollection<Book> Books { get; set; }
}
public class Book
{
public int Id { get; set; }
public int Title { get; set; }
}
Thanks.
Assuming you have a collection of authors, you would simply do
var author = authors.SingleOrDefault(x=> x.Books.Any(y=> y.Title.Equals(bookTitle, StringComparison.OrdinalIgnoreCase))
This assumes that books have only one author.
You can achieve it in this simple way, Demo on dotnetfiddle
var result = authors.SelectMany(a => a.Books.Select(b => new { BookTitle = b.Title, AuthorName = a.AuthorName }));

EF Core - Cannot add object with composite key

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();

can i insert some specific fields from one table to a class

is it possible insert some specific fields from one table to a class in mvc?
for example i have tbl_User . can i insert just field "Name" in "MyClass"?
i wanna pass a model(MyClass) to view that contains some fields of tbl_User .
and i used codefirst.
public class MyClass:tbl_User
{
//i mean can i put some fields of tbl_User instead below code .
//but below code insert all fields of tbl_User
public List<tbl_User> tbl_User { get; set; }
}
Yes, you can; see the code below.
// get /users
public ActionResult Index()
{
using (var db = new YourContext())
{
// We just need to show user name and id will be used to perform actions like edit user ETC. So we have created a reduced model named UserIndexModel.
return db.Users.Select(u => new UserIndexModel { Id = u.Id, Name = u.Name}).ToList();
}
}
Model definitions:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string HashPassword { get; set; }
public DateTime CreatedOn { get; set; }
}
public class YourContext : DbContext
{
public DbSet<User> Users { get; set; }
}
View model:
public class UserIndexModel
{
public int Id { get; set; }
public string Name { get; set; }
}

How do I chain properties with Code First entity framework?

I'm trying to do what seems fairly simple but I'm getting a null reference....
I have a null on the assoc files property in the last statement...
TestInfo.AggregateRoutes.MainBlogEntry = new Blog { BlogType = 1, Title = TestInfo.UniqueRecordIdentifier, Description = TestInfo.UniqueRecordIdentifier, DateAdded = DateTime.Now, User = TestInfo.UniqueRecordIdentifier };
IBlogRepository blogRepo = new BlogRepository();
var assocFile = new AssocFile { Name = TestInfo.UniqueRecordIdentifier, Url = TestInfo.UniqueRecordIdentifier };
TestInfo.AggregateRoutes.MainBlogEntry.AssocFiles.Add(assocFile);
This is the code I have written to support what I'm trying to do...
public class PteDotNetContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<AssocFile> AssocFiles { get; set; }
}
public class Blog
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BlogId { get; set; }
public int BlogType { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime DateAdded { get; set; }
public string User { get; set; }
public virtual ICollection<AssocFile> AssocFiles { get; set; }
}
public class AssocFile
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AssocFileId { get; set; }
public int BlogId { get; set; }
public string Url { get; set; }
public string Name { get; set; }
public virtual Category Category { get; set; }
}
I thought the whole point in declaring it virtual was that it would create a foreign key constraint?
When you instantiate an entity you also need to initialize the collection navigational properties before you access it for the first time. In your case MainBlogEntry.AssocFiles = new List<AssocFile>();. The reason for this is, your property implementation does not contain any logic to initialize the collection.
When EF creates new instances of your entities, it sub classes your entities (ie Proxy Creation) and over ride the default functionality of your properies.
TestInfo.AggregateRoutes.MainBlogEntry = new Blog { BlogType = 1, Title = TestInfo.UniqueRecordIdentifier, Description = TestInfo.UniqueRecordIdentifier, DateAdded = DateTime.Now, User = TestInfo.UniqueRecordIdentifier };
IBlogRepository blogRepo = new BlogRepository();
var assocFile = new AssocFile { Name = TestInfo.UniqueRecordIdentifier, Url = TestInfo.UniqueRecordIdentifier };
TestInfo.AggregateRoutes.MainBlogEntry.AssocFiles = new List<AssocFile>();
TestInfo.AggregateRoutes.MainBlogEntry.AssocFiles.Add(assocFile);