Insert in relationship table after inserting record - entity-framework-core

I have this classes and a WebApi method to POST the Item.
After inserting Item i want it to insert the inserted PK ItemId and given CategoryId into CategoryItem
public partial class Item
{
public int Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public string? Type { get; set; }
}
public partial class Category
{
public int Id { get; set; }
public string? Description { get; set; }
public string? Name { get; set; }
}
public partial class Categoryitem
{
public int IdCategory { get; set; }
public int IdItem { get; set; }
public virtual Category IdCategoryNavigation { get; set; } = null!;
public virtual Item IdItemNavigation { get; set; } = null!;
}
[HttpPost]
public ActionResult<Item> PostItem(Item item)
{
_context.Item.Add(item);
_context.SaveChanges();
return Ok();
}
How do i pass the IdCategory into POST method ? Do I need a CategoryCollection in Item class and pass IdCategory through Item member ?
What about the relationship table ? How do i insert the two Ids ?
Thank you

you can create a viewmodel if you need to add several categories in the same time when you create an item, or if you only assign one category when you create an item you can just add CategoryId, but with attribute [NotMapped]
public partial class Item
{
public int Id { get; set; }
... another properties
[NotMapped]
public int? CategoryId{ get; set; }
}
or fluent api
modelBuilder.Entity<Item>().Ignore(c => c.CategoryId);
you will have to bind this CategoryId to dropdown list in the view
and action
[HttpPost]
public ActionResult<Item> PostItem(Item item)
{
var categoryitem = new Categoryitem
{
IdItemNavigation=item,
IdCategory = item.CategoryId
};
_context.Categoryitem.Add(categoryitem);
_context.SaveChanges();
return Ok(item);
}

Related

Issue while converting IFormFile to string

I am working a asp.netcore 3.1 project. I have 2 table with one to many relationship.
I am facing an issue in converting VideoId form IFormFile to String.
Here is my model and viewModel.
ParentModel.cs
public class Parent
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public List<child> Children { get; set; }
}
public class child
{
public int Id { get; set; }
public string VideoId { get; set; } // inside ParentModel videoId is string type
public int ParentId { get; set; }
}
ParentViewModel.cs
public class Parent
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public List<child> Children { get; set; }
}
public class child
{
public int Id { get; set; }
public IFormFile VideoId { get; set; } // inside ParentViewModel VideoId is IFormFile type
public int ParentId { get; set; }
}
ParentController.cs
public async Task<IActionResult> Create([FromForm] ParentViewModel parent)
{
var result = await _ParentService.Create(_mapper.Map<ParentModel>(parent)); // this line is ok. After this line VideoId is Microsoft.AspNetCore.Http.FormFile
if (parent.Child.Count > 0)
{
int id = 0;
foreach (var child in parent.Child){
var videoIdString = await _helper.UploadImage(child.VideoId, "path"); // In this line I convert videoId of child of ParentViewModel to string from IFormFile. Now VideoId is path.mp4
}
id++;
}
// I have to update VideoId of child of ParentModel with that coverted videoIdString
await _ParentService.Update(result);
return Created(nameof(Get), result);
}
I have to update VideoId of the child of ParentModel with converted videoIdString
How Can I do this? Anyone ideas, please...
first you don't need this DatabaseGenerated(DatabaseGeneratedOption.Identity)
because the default is on trying to understand from my code
public class MParent
{
[Key]
public int Id { get; set; }
public List<child> Children { get; set; }
}
public class Mchild
{
[Key]
public int Id { get; set; }
public string VideoId { get; set; }
public int ParentId { get; set; }
}
and view model
public class Parent
{
public int Id { get; set; }
public List<child> Children { get; set; }
}
public class child
{
public int Id { get; set; }
public IFormFile VideoId { get; set; }
public int ParentId { get; set; }
}
and my controller
[HttpPost]
public IActionResult Create(child child, IFormFile myfile)
{
Mchild mychild = new Mchild()
{
ParentId = child.ParentId,
VideoId = myfile.FileName
};
myfile.CopyToAsync(myfileLoctionTosaveVideo);
_context.add(mychild);
_context.savechanges();
return View();
}
and you can do these with file

SqlException: Cannot insert the value NULL into column 'Description', table 'dbo.Shifts'; column does not allow nulls. INSERT fails

I am trying to insert parent data only, not child object. Related foreign key property object is null, but still EF core is trying to insert child object. Here is my objects -
public class Shift
{
public int ShiftUID { get; set; }
public string Description { get; set; }
public bool? IsActive { get; set; }
public virtual ICollection<AOCSchedule> AOCSchedules { get; set; }
}
public class AOCSchedule
{
public int AOCUID { get; set; }
public DateTime ScheduleDate { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public int ShiftUID { get; set; }
public Shift Shift { get; set; }
public string Name { get; set; }
public bool? IsActive { get; set; }
}
and here is my Add method -
public async Task<AOCSchedule> AddAOCScheduleAsync(AOCSchedule entity)
{
_dbContext.Entry(entity.Shift).State = EntityState.Detached;
await _dbContext.Set<AOCSchedule>().AddAsync(entity);
await _dbContext.SaveChangesAsync();
return entity;
}
Since there is no data in child object (Shift), so it throws the exception. Also I tried marking child entity state as Unmodified, but didn't work. Please help. Thanks in advance.
The models you use is that Shift is parent and AOCSchedule is child. EFCore doesn't allow to save child data without parent's data. That's why you get error. You need to re-design your database if you want AOCSchedule to be parent table.
For example, remove ShiftUID from AOCSchedule and add AOCUID in Shift table.
1. Just make the foreign key nullable:
public class AOCSchedule
{
public int AOCUID { get; set; }
public DateTime ScheduleDate { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public int? ShiftUID { get; set; } //public int ShiftUID { get; set; }
public virtual Shift Shift { get; set; } //public Shift Shift { get; set; }
public string Name { get; set; }
public bool? IsActive { get; set; }
}
2. Comment out this line because this is no shift posted from view
_dbContext.Entry(entity.Shift).State = EntityState.Detached;
Codes of controller
[HttpPost]
public async Task<IActionResult> AddAOCScheduleAsync([Bind("AOCUID,ScheduleDate,StartTime,EndTime,ShiftUID,Name,IsActive")] AOCSchedule entity)
{
//_dbContext.Entry(entity.Shift).State = EntityState.Detached;
await _dbContext.Set<AOCSchedule>().AddAsync(entity);
await _dbContext.SaveChangesAsync();
//return entity;
return RedirectToAction(nameof(Index));
}
Test of result

Table Id field automatically append with table name that produce invalid column name

I have table Categories With Id column when insert occur is shows it shows errorSqlException: Invalid column name 'CategoriesId'.
public partial class Categories
{
public Categories()
{
CategoryTabs = new HashSet<CategoryTabs>();
}
public int Id { get; set; }
public string Title { get; set; }
public int? ParentId { get; set; }
public int? SeasonId { get; set; }
public int? Levels { get; set; }
public string Image { get; set; }
public string Description { get; set; }
public virtual Seasons Season { get; set; }
public List<Categories> children { get; set; }
public virtual ICollection<CategoryTabs> CategoryTabs { get; set; }
}
public partial class CategoryTabs
{
public int Id { get; set; }
public int? CategoryId { get; set; }
public int? TabId { get; set; }
public virtual Categories Category { get; set; }
public virtual Tabs Tab { get; set; }
}
CategoriesId is the conventional name for the Foreign Key property/column associated with the one-to-many self relationship introduced by
public List<Categories> children { get; set; }
collection navigation property inside Categories entity.
Looking at the entity model, most likely the idea was to use the ParentId for that purpose. Since it doesn't match EF Core naming conventions, it has to be mapped explicitly by using either ForeignKey data annotation:
[ForeignKey(nameof(ParentId))]
public List<Categories> children { get; set; }
or fluent API inside OnModelCreating override:
modelBuilder.Entity<Categories>()
.HasMany(e => e.children)
.WithOne()
.HasForeignKey(e => e.ParentId);

One To Many Relationships field always null

Hi Everyone When I was trying to use Model.SubCategories but it is always null. I Don't understand anything.
MyModel like this:
public class Category
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int CategoryID { get; set; }
public string Name { get; set; }
public virtual IEnumerable<SubCategory> SubCategories { get; set; }
}
public class SubCategory
{
[Key]
public int SubCategoryID { get; set; }
public string Name { get; set; }
[ForeignKey("Category")]
public int CategoryID { get; set; }
public virtual Category Category { get; set; }
}
DBContext Like This:
public class EntitiesContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<SubCategory> SubCategories { get; set; }
}
My Action Like this:
public ActionResult Index()
{
return View(database.Categories.ToList());
}
My Views snippet Like This:
#foreach (var item in Model.SubCategories) //always null
{
//...
}
Try to declare SubCategory property as ICollection instead of IEnumerable.
SubCategories are virtual, which means lazy loading. That means, the table will not be retrieved, unless you request it. Use Include method.
public ActionResult Index()
{
return View(database.Categories.Include("SubCategory").ToList());
}

Child objects in domain class

I have a domain class like
public class Category
{
[Key]
public string IdCategory { get; set; }
public string Name { get; set; }
public List<Category> Children { get; set; }
public List<Product> Products { get; set; }
public Category()
{
Products = new List<Product>();
Children = new List<Category>();
}
}
In the generated code I find the products collection, but not the children collection. There are some restriction about using the same class? There is another way to modeling this relation without recurring to keys?
public class Category
{
[Key]
public string IdCategory { get; set; }
public string Name { get; set; }
public string IdFather { get; set; }
public List<Product> Products { get; set; }
[Include]
[Association("ParentChild", "IdCategory", "IdFather")]
public List<Category> Children { get; set; }
public Category()
{
Products = new List<Product>();
Children = new List<Category>();
}
}