i have a course management app and i have an issue when i try to add a student to a course studentsList.
when save changes run the student list changes from a list which contains old elements+ the new element to a list with only the new element (the last student added) and then saves it to database.
using EntityFramework 5.0.0
relationship declaration and seeding in context OnModelCreating()
modelBuilder.Entity<Course>().HasMany<Student>(c => c.StudentsList).WithMany(s => s.Courses).UsingEntity(t => t.HasData(
new { CoursesCourseId = Convert.ToInt64(1), StudentsListStudentId="id1"},
new { CoursesCourseId = Convert.ToInt64(1), StudentsListStudentId="id2"},
new { CoursesCourseId = Convert.ToInt64(1), StudentsListStudentId="id3"}
));
models
public class Course
{
public long CourseId { get; set; }
public string CourseName { get; set; }
public IEnumerable<Lesson> LessonsList { get; set; }
public DateTime CourseStartDate { get; set; }
public DateTime CourseEndDate { get; set; }
public List<Student> StudentsList { get; set; }
public class Student
{
[Key]
public string StudentId { get; set; }
public List<Course> Courses { get; set; }
}
controller action
[HttpPatch("{id}")]
public async Task<IActionResult> RegisterStudentToCourse(long id, [FromBody] List<string> studentsIds)
{
Course course = await _courseRepo.GetCourse(id);
if (course == null || !studentsIds.Any())
return BadRequest();
IEnumerable<Lesson> list = await _lessonRepo.GetLessons(id);
List<Lesson> lessonsList = list.ToList();
List<Student> studentsList = course.StudentsList.ToList();
foreach (string studentId in studentsIds)
{
Student student = _studetRepo.GetStudent(studentId);
if (student == null)
return BadRequest();
if (studentsList.Contains(student))
continue;
//HERE IS THE CALL TO THE REPOSITORY ADDSTUDENT
await _courseRepo.AddStudent(id, studentId);
foreach (Lesson l in lessonsList)
{
Attendance attendance = await _attendanceRepo.CreateAttandance(studentId);
await _lessonRepo.AddAttendance(l.LessonId, attendance);
}
}
_context.SaveChanges();
return Ok();
}
repository function
public async Task<bool> AddStudent(long id, string studentId)
{
Course course = await _context.Courses.Include(c => c.StudentsList).FirstOrDefaultAsync(c => c.CourseId == id);
Student student = await _context.Students.FirstOrDefaultAsync(s => s.StudentId == studentId);
if (course == null || student==null)
return false;
course.StudentsList.Add(student);
return await _context.SaveChangesAsync() > 0;
}
Related
`Suppose, I've User list with list of order
User model
`public class User
{
public int Id { get; set; }
public string Name { get; set; }
public List<UserOrder> Orders { get; set; }
}`
User Order model
`public class UserOrder
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
}`
Order model
`public class Order
{
public int Name { get; set; }
public decimal Price { get; set; }
}`
Here, I want to retrieve all user list that contain all element of List in UserOrder list. (Compare with Name and Price)`
I don't quite understand what you mean, do you want to include the current Orders list when querying User?
You need to link the two tables. For example, add a field UserId to the UserOrder model to associate with User; or add a List<int> to the User model to store the corresponding UserOrderId.
I made a simple test, you can refer to it. In order to facilitate maintenance, I will write the method of processing data from the database in a separate service:
User Model:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public List<int> UserOrderIds { get; set; }
public List<UserOrder> Orders { get; set; }
}
UserService:
public class UserService
{
private readonly IMongoCollection<User> _users;
public UserService(IUserDatabaseSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
_users = database.GetCollection<User>(settings.UserCollectionName);
}
public async Task<List<User>> GetAllAsync()
{
return await _users.Find(s => true).ToListAsync();
}
public async Task<User> GetByIdAsync(int id)
{
return await _users.Find<User>(s => s.Id == id).FirstOrDefaultAsync();
}
public async Task<User> CreateAsync(User user)
{
await _users.InsertOneAsync(user);
return user;
}
public async Task UpdateAsync(int id, User user)
{
await _users.ReplaceOneAsync(s => s.Id == id, user);
}
public async Task DeleteAsync(int id)
{
await _users.DeleteOneAsync(s => s.Id == id);
}
}
UserOrderService:
public class UserOrderService
{
private readonly IMongoCollection<UserOrder> _userOrders;
public UserOrderService(IUserDatabaseSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
_userOrders = database.GetCollection<UserOrder>(settings.UserOrderCollectionName);
}
public async Task<List<UserOrder>> GetAllAsync()
{
return await _userOrders.Find(s => true).ToListAsync();
}
public async Task<UserOrder> GetByIdAsync(int id)
{
return await _userOrders.Find<UserOrder>(c => c.Id == id).FirstOrDefaultAsync();
}
public async Task<UserOrder> CreateAsync(UserOrder userOrder)
{
await _userOrders.InsertOneAsync(userOrder);
return userOrder;
}
public async Task UpdateAsync(int id, UserOrder userOrder)
{
await _userOrders.ReplaceOneAsync(c => c.Id == id, userOrder);
}
public async Task DeleteAsync(int id)
{
await _userOrders.DeleteOneAsync(c => c.Id == id);
}
}
appsetting.json:
"UserDatabaseSettings": {
"UserCollectionName": "User",
"UserOrderCollectionName": "UserOrder",
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "TestDb"
}
IUserDatabaseSettings(Used to obtain database related information):
public interface IUserDatabaseSettings
{
string UserCollectionName { get; set; }
string UserOrderCollectionName { get; set; }
string ConnectionString { get; set; }
string DatabaseName { get; set; }
}
public class UserDatabaseSettings : IUserDatabaseSettings
{
public string UserCollectionName { get; set; }
public string UserOrderCollectionName { get; set; }
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
Registration service:
services.Configure<UserDatabaseSettings>(
Configuration.GetSection(nameof(UserDatabaseSettings)));
services.AddSingleton<IUserDatabaseSettings>(provider =>
provider.GetRequiredService<IOptions<UserDatabaseSettings>>().Value);
services.AddSingleton<UserService>();
services.AddSingleton<UserOrderService>();
Controller:
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly UserService _userService;
private readonly UserOrderService _userOrderService;
public UserController(UserService sService, UserOrderService cService)
{
_userService = sService;
_userOrderService = cService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<User>>> GetAll()
{
var users = await _userService.GetAllAsync();
return Ok(users);
}
[HttpGet("{id}")]
public async Task<ActionResult<User>> GetById(int id)
{
var user = await _userService.GetByIdAsync(id);
if (user == null)
{
return NotFound();
}
if (user.UserOrderIds.Count > 0)
{
var tempList = new List<UserOrder>();
foreach (var userOrderId in user.UserOrderIds)
{
var userOrder = await _userOrderService.GetByIdAsync(userOrderId);
if (userOrder != null)
tempList.Add(userOrder);
}
user.Orders = tempList;
}
return Ok(user);
}
[HttpPost]
public async Task<IActionResult> Create(User user)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
await _userService.CreateAsync(user);
return Ok(user);
}
[HttpPut]
public async Task<IActionResult> Update(int id, User updatedUser)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
var queriedStudent = await _userService.GetByIdAsync(id);
if (queriedStudent == null)
{
return NotFound();
}
await _userService.UpdateAsync(id, updatedUser);
return NoContent();
}
[HttpDelete]
public async Task<IActionResult> Delete(int id)
{
var student = await _userService.GetByIdAsync(id);
if (student == null)
{
return NotFound();
}
await _userService.DeleteAsync(id);
return NoContent();
}
}
Test Result:
Complete example is here.
I am working on a Blazor Server Application that has a Radzen master-detail data grid. This data grid is populated with IsActive = 1 data OnInitializedAsync method.
Here is the Order repository and related query which retrieves active data:
namespace IMS.Plugins.EFCore
{
public class OrderRepository : IOrderRepository
{
private readonly IMSContext _db;
public OrderRepository(IMSContext db)
{
_db = db;
}
public async Task<IEnumerable<Order?>> GetAllOrders(ClaimsPrincipal user)
{
if (user.IsInRole("Administrators"))
{
return await _db.Orders.Include(d => d.OrderDetails.Where(od => od.IsActive == 1)).ThenInclude(v => v.Vendor).ToListAsync();
}
return await _db.Orders.Include(d => d.OrderDetails.Where(od => od.IsActive == 1)).ThenInclude(v => v.Vendor).ToListAsync();
}
}
}
Here is the Detail repository which sets the related order detail to IsActive = 0
namespace IMS.Plugins.EFCore
{
public class OrderDetailRepository : IOrderDetailRepository
{
private readonly IMSContext _db;
public OrderDetailRepository(IMSContext db)
{
_db = db;
}
public async Task PassiveOrderDetailAsync(OrderDetail orderDetail)
{
var detail = await this._db.OrdersDetail.FindAsync(orderDetail.Id);
if (detail != null)
{
detail.IsActive = 0; // 0-Passive
await _db.SaveChangesAsync();
}
}
}
}
Here is the master-detail data grid populated OnInitializedAsync method. By the way, this part is working. (gets IsActive = 1)
protected override async Task OnInitializedAsync()
{
user = (await _authenticationStateProvider.GetAuthenticationStateAsync()).User;
//userName = user.Identity.Name;
if (!user.Identity.IsAuthenticated)
{
NavigationManager.NavigateTo("/Identity/Account/Login", false);
}
_orders = await ViewAllOrdersUseCase.ExecuteAsync(user);
SelectedOrders = new List<Order?> { _orders.FirstOrDefault() };
_vendors = await ViewAllVendorsUseCase.ExecuteAsync();
_customers = await ViewAllCustomersUseCase.ExecuteAsync();
}
The problem starts when I try to update a detail to IsActive = 0 as shown on the screenshot.
Related Blazor:
<RadzenButton Icon="delete" ButtonStyle="ButtonStyle.Danger" Class="m-1" Click="#(args => PassiveDetail(detail))">
</RadzenButton>
Here is what I do in the related portion:
RadzenDataGrid<OrderDetail> _gridDetail;
IEnumerable<Order?> _orders = new List<Order?>();
...
async Task PassiveDetail(OrderDetail orderDetail)
{
if (orderDetail == _detailToInsert)
{
_detailToInsert = null;
}
await _gridDetail.UpdateRow(orderDetail);
await PassiveOrderDetailUseCase.ExecuteAsync(orderDetail);
_orders = await ViewAllOrdersUseCase.ExecuteAsync(user);
StateHasChanged();
}
Selected row updated successfully but when this line calls _orders = await ViewAllOrdersUseCase.ExecuteAsync(user); it still gets the old data IsActive = 0. I couldn't find out why? However, OnInitializedAsync method works as excepted. Frankly, I couldn't solve.
Edit 1
Is it because there are 2 separate repositories for both order and order details? They are having their own insert and updates?
Edit 2
I should have added earlier Order and OrderDetail entities:
public class Order
{
public int Id { get; set; }
[Required]
public DateTime OrderDateTime { get; set; }
[Required]
[MaxLength(250)]
public int CustomerId { get; set; }
public string Status { get; set; }
[MaxLength(50)]
public string DoneBy { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
public Customer Customer { get; set; }
}
public class OrderDetail
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string ProductCode { get; set; }
[Required]
[MaxLength(250)]
public string ProductName { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public double BuyUnitPrice { get; set; }
public double CostRatio { get; set; }
public double UnitCost { get; set; }
public double TotalBuyPrice { get; set; }
public double? SellUnitPrice { get; set; }
public double? TotalSellPrice { get; set; }
[MaxLength(150)]
public string? ShippingNumber { get; set; }
public string? Status { get; set; }
[MaxLength(150)]
public string? TrackingNumber { get; set; }
[MaxLength(400)]
public string? Description { get; set; }
public string? Currency { get; set; }
public string? CustomerStockCode { get; set; }
public string? CustomerOrderNumber { get; set; }
public int IsActive { get; set; }
public double? TotalUnitCost { get; set; }
public int OrderId { get; set; }
public int VendorId { get; set; }
public Order Order { get; set; }
public Vendor Vendor { get; set; }
}
Edit 3
I think I found the suspect. The query below shouldn't get the IsActive=0 but it somehow gets! Any ideas for this situation?
Here is the query:
public async Task<IEnumerable<Order?>> GetAllOrders(ClaimsPrincipal user)
{
if (user.IsInRole("Administrators"))
{
return await _db.Orders.Include(d => d.OrderDetails.Where(od => od.IsActive == 1)).ThenInclude(v => v.Vendor).ToListAsync();
}
return await _db.Orders.Include(d => d.OrderDetails.Where(od => od.IsActive == 1)).ThenInclude(v => v.Vendor).ToListAsync();
}
The record is updated, why is the query doesn't work the way it is expected? First I am updating then I am querying IsActive = 1
await PassiveOrderDetailUseCase.ExecuteAsync(orderDetail); //sets to IsActive = 0
_orders = await ViewAllOrdersUseCase.ExecuteAsync(user); // calls GetAllOrders method above,should get only the actives IsActive = 1
But IsActive = 0 also comes inside of _orders as seen in the screenshot below.
Edit 4
When I add AsNoTracking() the query in my previous post gets only IsActive = 1 that is what I want but somehow doesn't get the Customer which is why I want to include it. Order have 2 children, Customer and OrderDetail. OrderDetail has one, Vendor. Couldn't manage to include Customer tough to the query.
This works so far.
Orders
.Include(d => d.OrderDetails.Where(od => od.IsActive == 1))
.ThenInclude(v => v.Vendor)
.Include(c => c.Customer)
.AsNoTracking()
.ToListAsync();
I'm using the solution provided by this link: AutoMapper don't work with entity EF Core
My problem is when using $top, #odata.count always return the number informed in $top but should return the number of total record.
I know that ODataQueryOptions has a property “Count”, but I don't know if it's possible to use to solve the problem
I'm using the below the code provided by Дмитрий Краснов in his question including the solution by Ivan Stoev:
There is entities:
public class LessonCatalog {
public string Name { get; set; }
public int? ImageId { get; set; }
public virtual Image Image { get; set; }
public virtual ICollection<Lesson> Lessons { get; set; }
}
public class Lesson {
public string Name { get; set; }
public string Description { get; set; }
public int? ImageId { get; set; }
public virtual Image Image { get; set; }
public int LessonCatalogId { get; set; }
public virtual LessonCatalog LessonCatalog { get; set; }
}
Views:
public class LessonView {
public string Name { get; set; }
public string Description { get; set; }
public int? ImageId { get; set; }
public ImageView Image { get; set; }
public int LessonCatalogId { get; set; }
public LessonCatalogView LessonCatalog { get; set; }
}
public class LessonCatalogView {
public string Name { get; set; }
public int? ImageId { get; set; }
public ImageView Image { get; set; }
public IEnumerable<LessonView> Lessons { get; set; }
}
My maps:
CreateMap<LessonCatalog, LessonCatalogView>()
.ForMember(dest => dest.Image, map => map.ExplicitExpansion())
.ForMember(dest => dest.Lessons, map => map.ExplicitExpansion());
CreateMap<Lesson, LessonView>()
.ForMember(dest => dest.LessonCatalog, map => map.ExplicitExpansion());
In my repository:
protected readonly DbContext _context;
protected readonly DbSet<TEntity> _entities;
public Repository(DbContext context) {
_context = context;
_entities = context.Set<TEntity>();
}
public IEnumerable<TView> GetOData<TView>(ODataQueryOptions<TView> query,
Expression<Func<TEntity, bool>> predicate = null) {
IQueryable<TEntity> repQuery = _entities.AsQueryable();
IQueryable res;
if (predicate != null) repQuery = _entities.Where(predicate);
if (query != null) {
string[] expandProperties = GetExpands(query);
//!!!
res = repQuery.ProjectTo<TView>(Mapper.Configuration, null, expandProperties);
//!!!
var settings = new ODataQuerySettings();
var ofilter = query.Filter;
var orderBy = query.OrderBy;
var skip = query.Skip;
var top = query.Top;
if (ofilter != null) res = ofilter.ApplyTo(res, settings);
if (orderBy != null) res = orderBy.ApplyTo(res, settings);
if (skip != null) res = skip.ApplyTo(res, settings);
if (top != null) res = top.ApplyTo(res, settings);
} else {
res = repQuery.ProjectTo<TView>(Mapper.Configuration);
}
return (res as IQueryable<TView>).AsEnumerable();
}
If my query result has 1007 records, and I use
…$count=true&$top=5
the result for count should be
"#odata.count": 1007
But instead the result is always
"#odata.count": 5
Using SQL Server Profile I can see that the Select for count is including the “top”. So, how to avoid this to happen?
I received a help from the Github Guy (thanks to #Gennady Pundikov) and could now answer this question.
I changed the GetOData Method to get the Count before apply others settings:
public IEnumerable<TView> GetOData<TView>(ODataQueryOptions<TView> query,
Expression<Func<TEntity, bool>> predicate = null) {
IQueryable<TEntity> repQuery = _entities.AsQueryable();
IQueryable res;
if (predicate != null) repQuery = _entities.Where(predicate);
if (query != null) {
string[] expandProperties = GetExpands(query);
//!!!
res = repQuery.ProjectTo<TView>(Mapper.Configuration, null, expandProperties);
//!!!
var settings = new ODataQuerySettings();
var ofilter = query.Filter;
var orderBy = query.OrderBy;
var skip = query.Skip;
var top = query.Top;
if (ofilter != null) res = ofilter.ApplyTo(res, settings);
if (query.Count?.Value == true)
{
// We should calculate TotalCount only with filter
// http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part2-url-conventions.html#_Toc371341773
// 4.8 Addressing the Count of a Collection
// "The returned count MUST NOT be affected by $top, $skip, $orderby, or $expand.
query.Request.ODataFeature().TotalCount = ((IQueryable<TView>)res).LongCount();
}
if (top != null) res = top.ApplyTo(res, settings);
if (orderBy != null) res = orderBy.ApplyTo(res, settings);
if (skip != null) res = skip.ApplyTo(res, settings);
} else {
res = repQuery.ProjectTo<TView>(Mapper.Configuration);
}
return (res as IQueryable<TView>).AsEnumerable();
}
Consider the following error:
InvalidOperationException: The instance of entity type 'OrderRegion' cannot be tracked because another instance with the key value '[Orderid: 10, RegionId: 1]' is already being tracked...
Also, consider the following classes (slightly snipped for brevity):
public class Order
…
[Key]
public int Id { get; set; }
…
[Display(Name = "Regions")]
public ICollection<OrderRegion> OrderRegions { get; set; }
[Display(Name = "Stores")]
public ICollection<OrderStore> OrderStores { get; set; }
public class OrderRegion
{
//[Key]
public int OrderId { get; set; }
public Order Order { get; set; }
//[Key]
public int RegionId { get; set; }
public Region Region { get; set; }
}
public class OrderStore
{
//[Key]
public int OrderId { get; set; }
public Order Order { get; set; }
//[Key]
public int StoreId { get; set; }
public Store Store { get; set; }
}
Also of relevance is the Context where I create the relationships:
public class MyContext:DbContext
{
public MyContext(DbContextOptions<AzureOrdersContext> options) : base(options) { }
public DbSet<Order> Order { get; set; }
public DbSet<OrderRegion> OrderRegion { get; set; }
public DbSet<OrderStore> OrderStore { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
…
modelBuilder.Entity<OrderRegion>()
.HasKey(nr => new { nr.OrderId, nr.RegionId });
modelBuilder.Entity<OrderRegion>()
.HasOne(nr => nr.Order)
.WithMany(n => n.OrderRegions)
.HasForeignKey(nr => nr.OrderId);
modelBuilder.Entity<OrderRegion>()
.HasOne(nr => nr.Region)
.WithMany(n => n.OrderRegions)
.HasForeignKey(nr => nr.RegionId);
modelBuilder.Entity<OrderStore>()
.HasKey(nr => new { nr.OrderId, nr.StoreId });
modelBuilder.Entity<OrderStore>()
.HasOne(nr => nr.Order)
.WithMany(n => n.OrderStores)
.HasForeignKey(nr => nr.OrderId);
modelBuilder.Entity<OrderStore>()
.HasOne(nr => nr.Store)
.WithMany(n => n.OrderStores)
.HasForeignKey(nr => nr.StoreId);
}
}
And finally, my "Edit.cshtml.cs" where my error is thrown (snipped a lot):
public async Task<IActionResult> OnPostAsync(int? id, int[] AssignedRegions, int[] AssignedStores)
{
if (!ModelState.IsValid)
{
return Page();
}
var Ordertoupdate = await _context.Order
.Include(i => i.OrderRegions).ThenInclude(navigationPropertyPath: i => i.Region)
.Include(i => i.OrderStores).ThenInclude(navigationPropertyPath: i => i.Store)
.FirstOrDefaultAsync(m => m.Id == id);
...
if (await TryUpdateModelAsync<Web.Models.Order>(
Ordertoupdate,
"Order",
i => i.CreatedOn,
i => i.CreatedBy,
i => i.ModifiedBy, i => i.ExpirationDate,
...))
{
UpdateOrderRegions(_context, AssignedRegions, Ordertoupdate);
UpdateOrderStores(_context, AssignedStores, Ordertoupdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateOrderRegions(_context, AssignedRegions, Ordertoupdate);
UpdateOrderStores(_context, AssignedStores, Ordertoupdate);
PopulateAssignedRegions(_context, Ordertoupdate);
PopulateAssignedStores(_context, Ordertoupdate);
return Page();
}
The error is getting thrown on _context.SaveChangesAsync(); Any ideas? I'm certain I'm just doing something stupid and not seeing a simple fix.
Updating to include UpdateOrderRegions as requested:
public void UpdateOrderRegions (AzureOrdersContext _context, int[] SelectedRegions, Web.Models.Order OrderToUpdate)
{
if (SelectedRegions == null)
{
OrderToUpdate.OrderRegions = new List<OrderRegion>();
return;
}
var StoreRegionsToDelete= OrderToUpdate.OrderRegions.Where<OrderRegion>(nr => {
return !SelectedRegions.AsQueryable<Int32>().Contains<Int32>(nr.RegionId);
});
StoreRegionsToDelete.ToList().ForEach(r => { OrderToUpdate.OrderRegions.Remove(r); });
var StoreRegionsToAdd = SelectedRegions.AsQueryable<Int32>().Where<Int32>(regionId =>
!OrderToUpdate.OrderRegions.Any( nr=> nr.RegionId == regionId)
);
StoreRegionsToAdd.ToList().ForEach(regionId =>
OrderToUpdate.OrderRegions.Add(new OrderRegion
{
OrderId = OrderToUpdate.Id,
RegionId = regionId
}));
////This is where a different, more frustrating logical error lives but isn't related to my EF error
////Attempting to model after: https://github.com/aspnet/Docs/blob/master/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/InstructorCoursesPageModel.cshtml.cs
var selectedRegionHS = new HashSet<string>(SelectedRegions);
var regionOrders = new HashSet<int>(OrderToUpdate.OrderRegions.Select(c => c.Order.Id));
foreach (var thisregion in _context.Region)
{
if (selectedRegionHS.Contains(thisregion.Id.ToString()))
{
if (!regionOrders.Contains(thisregion.Id))
{
OrderToUpdate.OrderRegions.Add(
new OrderRegion
{
OrderId = OrderToUpdate.Id,
RegionId = thisregion.Id
});
}
}
else
{
if (regionOrders.Contains(thisregion.Id))
{
OrderRegion RegionToRemove = OrderToUpdate.OrderRegions.SingleOrDefault(i => i.RegionId == thisregion.Id);
_context.Remove(RegionToRemove);
}
}
}
}
This issue occurs when the context already has an item tracked and you explicitly try attaching a new object with the same key.
Considering the error is on OrderRegion and this type has a composite key of OrderId/RegionId, I think it is likely that you are retrieving the OrderRegion and attaching a new OrderRegion with the same OrderId/RegionId combination. You may need to check if an OrderRegion key already exists or clear the Order's regions and rebuild the list to avoid this collision.
I hope this points you in the right direction. Feel free to provide the code where you handle the OrderRegion updates and I'll try to further assist.
I'm trying to update a simple model:
public class DayOff
{
public int Id { get; set; }
public List<User> Users { get; set; }
public DayOff()
{
Users = new List<User>();
}
}
my service layer is:
public void Update(DayOff dayOff, IEnumerable<int> users)
{
var dayOffToUpdate = _db.DayOff.Include("Users").Single(d => d.Id == dayOff.Id);
dayOffToUpdate.Users.Clear();
_db.Entry(dayOffToUpdate).CurrentValues.SetValues(dayOff);
dayOffToUpdate.Users = _db.User.Where(u => users.Contains(u.Id)).ToList();
foreach (var user in dayOffToUpdate.Users)
{
_db.Entry(user).State = EntityState.Modified;
}
_db.SaveChanges();
}
but it is NOT updating the users, so how can I?