Updating multiple records with context, ASP.NET C# - c#

I want to find everything with a certain matching variable, and then update that variable.
Updating that exact variable for every record that was found.
I know context is used to query the database.
How could I do this?
Its not working:
public async Task<IActionResult> Checkout()
{
IEnumerable<Orders> orders = _ocontext.GetAllOrders();
var movingcart = orders.Where(p => p.Cart == 1);
foreach (var item in movingcart)
{
item.Cart++;
}
_context.Update(movingcart);
await _context.SaveChangesAsync();
return View();
}
EDIT::::
I FIGURED IT OUT!:
public async Task<IActionResult> Checkout()
{
var Temp = (from d in _context.Orders
where d.Cart == 1
select d).Single();
Temp.Cart++;
_context.Update(Temp);
await _context.SaveChangesAsync();
return View();
}

I missed this part where you said "I want to find everything with a certain matching variable, and then update that variable."
To do that, you could do this:
var cartItems = _context.Orders.Where(x => x.Cart == 1).ToList();
foreach (var item in cartItems)
{
item.Cart++;
_context.Update(item);
await _context.SaveChangesAsync();
}

public async Task<IActionResult> Checkout()
{
var temp= _context.Orders.FirstOrDefault(x => x.Cart == 1);
temp.Cart++;
_context.Update(temp);
await _context.SaveChangesAsync();
return View();
}

Related

LINQ Query - sql equivalent of select * from tablename where columnname =columnvalue

I am trying to find the LINQ equaivalent of
select * from usertable where groupof=groupuser
I have the following code
var UserList = await usertableservice.GetUsers() as List<UserTable>;
var query = from c in UserList
where c.GroupOf.Contains(groupuser)
select c;
return query.FirstOrDefault().UserId;
The GetUsers() function will list all the users then I filter if the groupof column contains a specific string.
But what happens here is
select * from usertable (this may contain 1 million records)
then I am filtering, I guess its totally wrong and resource intensive. What is the best way of doing this?
service layer code:
public async Task<IEnumerable<UserTable>> GetUsers()
{
try
{
var response = await httpClient.GetAsync("api/userinfo");
if (response.IsSuccessStatusCode)
{
if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
{
return Enumerable.Empty<UserTable>();
}
string s = await response.Content.ReadAsStringAsync();
//return Enumerable.Empty<LookupTable>();
return await response.Content.ReadFromJsonAsync<IEnumerable<UserTable>>();
}
else
{
var message = await response.Content.ReadAsStringAsync();
throw new Exception($"Http status code: {response.StatusCode} message: {message}");
}
}
catch (Exception ex)
{
//Log exception
throw;
}
}
controller code
[HttpGet]
public async Task<ActionResult<IEnumerable<UserTable>>> GetAllUsers()
{
try
{
var list = await this.userTableRepository.GetUsers();
if (list == null)
{
return NotFound();
}
else
{
//var LookuplistDtos = lookuplist.ConvertToDto();
return Ok(list);
}
}
catch (Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError,
"Error retrieving data from the database");
}
}
Repository code
public async Task<IEnumerable<UserTable>> GetUsers()
{
var item = await this.riskDBContext.UserTables
.ToListAsync();
return item;
}
The flow is
UI -> service layer -> api -> repository
I agree - it would be wrong to pass million items through api layer for filtering in UI layer.
IQueryable can't be used in UI layer because it can't be serialized - so it cannot be moved through Api layer.
All heavy data filtering should be in repository level but filtering parameter "groupuser" should be passed through flow from UI to repository.
For the sake of brevity and clarity, I did not include error handling here.
UI code:
var User = await usertableservice.GetUserByGroup(groupuser);
return User.UserId;
Service layer code:
public async Task<UserTable> GetUserByGroup(string userGroup)
{
var response = await httpClient.GetAsync("api/userbygruop?userGroup="+userGroup);
return await response.Content.ReadFromJsonAsync<UserTable>();
}
Api Controller code:
[HttpGet]
[Route("userbygruop")]
public async Task<ActionResult<UserTable>> GetUserByGroup(string userGroup)
{
var user = await this.userTableRepository.GetUserByGroup(userGroup);
return Ok(user);
}
Repository code:
public async Task<UserTable> GetUserByGroup(string userGroup)
{
var UsersQuery = this.riskDBContext.UserTables;
var query = from c in UsersQuery
where c.GroupOf.Contains(userGroup)
select c;
var filteredUser = await query.FirstOrDefaultAsync();
return filteredUser;
}

AutoMapper sets EF Core entities to detach state

When I map my input model with my database entities using AutoMapper, entity states are changes to 'detached' which means, that the changes aren't saved to the database.
CreateMap<User, UserInput>().ReverseMap();
Add/Update:
[BindProperty]
public IList<UserInput> UsersInput { get; set; }
public async Task<PageResult> OnGetAsync()
{
var users = await _dbContext.Users.ToListAsync();
UsersInput = _mapper.Map<List<UsersInput>>(signers);
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
var users = await _dbContext.Users.ToListAsync();
foreach (var u in users)
{
Console.WriteLine(_dbContext.Entry(u).State); // => Unchanged
}
users = _mapper.Map(UsersInput, users);
foreach (var u in users)
{
Console.WriteLine(_dbContext.Entry(u).State); // => Detached
}
// Save and return
await _dbContext.SaveChangesAsync(); // => Nothing is saved because entities are Detached
return Page();
}
Has it something to do with the way I map the data?
As long as UsersInput has an id that corresponds to the id in the Users table, then there's no reason to load anything from the DB. Just use the EF Core UpdateRange() method:
public async Task<IActionResult> OnPostAsync()
{
var users = _mapper.Map<List<User>>(UsersInput);
_dbContext.Users.UpdateRange(users);
await _dbContext.SaveChangesAsync();
return Page();
}

ASP.NET Core 5.0. Scaffolded controller variable names. C#

So when i scaffold a controller for my Event model it builds the typical GET/POST controller page.
It seems like every instance of the variable "event" has an # in front of it. If i try to remove the # it doesn't recognize the word as a variable (even with var in front of the word). Im pretty new to coding and i havent seen this before, what is causing this?
See examples below:
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var #event = await _context.Events
.FirstOrDefaultAsync(m => m.EventId == id);
if (#event == null)
{
return NotFound();
}
return View(#event);
}
public async Task<IActionResult> Create([Bind("EventId,Subject,Description,StartTime,EndTime,Theme,IsFullDay")] Event #event)
{
if (ModelState.IsValid)
{
_context.Add(#event);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(#event);
}
event is a reserved word, if use it, you have to add # in front of it. You can change it to other variable.
Here is all the Keywords.

Nothing happens when accessing an async task from repository in asp.net?

I am creating an async task in a repo, and then accessing it from the controller to try and minimize the logic in the controller.
The thing is, that when I used the exact same logic in the controller, there was an output, now that I'm accessing this way, it isn't searching for it.
Repository:
public async Task<List<Guests>> GetGuesteByAsync(string Search)
{
var list = GetAll();
var listquery = from x in context.Guest select x;
if (!string.IsNullOrEmpty(Search))
{
listquery = listquery.Where(x => x.FullName.Contains(Search) || x.Organisation.Contains(Search));
}
return await context.Guests.ToListAsync();
}
The controller:
[HttpGet]
public async Task<ActionResult> Index(string Search)
{
ViewData["Getsearchinput"] = EmpSearch;
//List<Guests> listofguests = await repository.GetGuesteByAsync(Search);
var res = await (repository.GetGuesteByAsync(Search));
return View(res);
}
This returns all entries.
return await context.Guests.ToListAsync();
I think you should use your query. Can you try this?
return await listquery.ToListAsync();

EF Core: A second operation started on this context before a previous operation completed

I appreciate this question has been asked. But I seem to have done what people are suggesting to fix it and I am still having the same issue. I can't see where I am going wrong. Any help would be greatly appreciated.
I am getting the following error:
InvalidOperationException: A second operation started on this context
before a previous operation completed. This is usually caused by
different threads using the same instance of DbContext
In these specific areas:
return await _dbContext.Set<T>().FindAsync(id);
var editPost = await _postRepository.GetByIdAsync(postModel.Id);
await _postAppService.Update(mapped);
await _postPageService.UpdatePost(Post);
Here is my code:
Just to add a bit more detail. I will list the exact steps:
First I select the post I would like to edit. The following gets called:
public async Task<IActionResult> OnGetAsync(int? postId)
{
if (postId == null)
{
return NotFound();
}
Post = await _postPageService.GetPostById(postId.Value);
if (Post == null)
{
return NotFound();
}
return Page();
}
public async Task<PostViewModel> GetPostById(int postId)
{
var post = await _postAppService.GetPostById(postId);
var mapped = _mapper.Map<PostViewModel>(post);
return mapped;
}
public async Task<PostModel> GetPostById(int postId)
{
var post = await _postRepository.GetByIdAsync(postId);
var mapped = ObjectMapper.Mapper.Map<PostModel>(post);
return mapped;
}
public virtual async Task<T> GetByIdAsync(int id)
{
return await _dbContext.Set<T>().FindAsync(id);
}
I then make my changes and click the update button:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
try
{
await _postPageService.UpdatePost(Post);
}
catch (DbUpdateConcurrencyException)
{
if (!PostExists(Post.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
public async Task UpdatePost(PostViewModel postViewModel)
{
var mapped = _mapper.Map<PostModel>(postViewModel);
if (mapped == null)
throw new Exception($"Entity could not be mapped.");
await _postAppService.Update(mapped);
_logger.LogInformation($"Entity successfully added - IndexPageService");
}
public async Task Update(PostModel postModel)
{
ValidatePostIfNotExist(postModel);
var editPost = await _postRepository.GetByIdAsync(postModel.Id);
if (editPost == null)
throw new ApplicationException($"Entity could not be loaded.");
ObjectMapper.Mapper.Map<PostModel, Post>(postModel, editPost);
await _postRepository.UpdateAsync(editPost);
_logger.LogInformation($"Entity successfully updated - AspnetRunAppService");
}
public async Task UpdateAsync(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
await _dbContext.SaveChangesAsync();
}
I have also set the lifetime of my DbContext to Transient.
services.AddDbContext<MyJourneyContext>(c => c.UseSqlServer(_config.GetConnectionString("MyJourneyConnectionString")),
ServiceLifetime.Transient);
So I am using await and have set the lifetime of my DbContext to Transient. But I am clearly still doing something wrong. Can anyone help me with this?

Categories

Resources