How to delete a row from database using lambda linq? - c#

I want to perform a delete operation to unfriend a user in a certain android application I'm developing. The following method returns "Done" but the data doesn't delete from the table. What is the problem here?
public string deleteFriend(int user, int friend) {
int i = db.Friends.Where(x => x.Person.Id == user && x.Person1.Id == friend).Select(x => x.Id).First();
var rec=db.Friends.ToList();
rec.RemoveAll(x=>rec.Any(xx=>xx.Id==i));
db.SaveChanges();
return "Done";
}
I'm working with Entity frame work LINQ.

Try something like this:
var friend = db.Friends.Where (x=>x.person.Id == user && x.Person1.Id == friend).FirstorDefault();
if (friend != null)
{
db.friends.Remove(friend);
db.SaveChanges()
}
if you have got multiple records than you can get rid of firstOrDefault and add .ToList() in the end.
And than use db.friends.RemoveRange(friend)
it is much cleaner and hope this helps
Thanks

using where id in (1,2,3)
List<int> ids = new List<int>(){1,2,3};
var table1 = _context.table1.Where(x => ids.Contains(x.Id)).ToList();
if (table1 != null && table1.Count > 0) {
_context.table1.RemoveRange(table1 );
_context.SaveChanges();
}

Related

The LINQ expression could not be translated - EF Core

In summary, I'm guessing I can't add any more complex calculations to the LINQ expression. Any tips are greatly appreciated!
This blazor project is using a messy employee table which contains two types of employees, both on the same table
Domestic employees, uses NRG number to identify them, but their NRG numbers are stored as string at NRG column, like "0356".
Foreign employees, also uses NRG to identify them, but their NRG column contains all NULL, their NRG numbers are inside their emails at AzureEmail column, like "johndoe.0356#aaa-bbb.com"
When domestic employee or foreign employee enter their sales records, they are the "Closer", it is required to enter the "Setter" NRG.
By using the "Setter" NRG number "closer" entered, I want to locate the "Setter" info from the same employee table:
public async Task Save_to_SalesForm()
{
await using var context3 = await DBContextFactory.CreateDbContextAsync();
{
if (salesForm.SetterNrg != null && salesForm.CsTransferCategory == "Local Team")
{
setterEmployee = context3.Employees.Where(
e => e.AzureAccountEnabled == 1
&&
(int?)(object?)e.Nrg == salesForm.SetterNrg
).OrderByDescending(e => e.EmployeeId).FirstOrDefault();
salesForm.SetterAgentFullName = setterEmployee.AzureFullName;
salesForm.SetterJobTitle = setterEmployee.AzureRole;
salesForm.SetterEmail = setterEmployee.AzureEmail;
salesForm.SetterTeam = setterEmployee.AzureTeam;
}
if (salesForm.SetterNrg != null && salesForm.CsTransferCategory == "CSR Team (Philippines)")
{
setterEmployee = context3.Employees.Where(
e => e.Nrg == null
&&
e.AzureAccountEnabled == 1
&&
e.AzureEmail.Contains("#aaa-bbb.com")
&&
(int?)(object?)e.AzureEmail.Split(new char[] { '.', '#' }, StringSplitOptions.RemoveEmptyEntries)[1] == salesForm.SetterNrg
).OrderByDescending(e => e.EmployeeId).FirstOrDefault();
salesForm.SetterAgentFullName = setterEmployee.AzureFullName;
salesForm.SetterJobTitle = setterEmployee.AzureRole;
salesForm.SetterEmail = setterEmployee.AzureEmail;
salesForm.SetterTeam = setterEmployee.AzureTeam;
}
}
context3.SalesForms.Add(salesForm);
await context3.SaveChangesAsync();
}
If the "Setter" is a domestic employee (Local Team), the above query works fine and be able to save the setter info to the table
If the "Setter" is a foreign employee (CSR Team (Philippines)), the above query won't work due to the .Split make the query too complex for LINQ expression. Error screenshot
I tried multiple ways to resolve the issue, but none seemed ideal.
I have rewritten your query to use EndsWith, which is translatable to the SQL:
public async Task Save_to_SalesForm()
{
await using var context3 = await DBContextFactory.CreateDbContextAsync();
if (salesForm.SetterNrg != null)
{
Employee? setterEmployee = null;
if (salesForm.CsTransferCategory == "Local Team")
{
setterEmployee = await context3.Employees
.Where(e => e.AzureAccountEnabled == 1
&& (int?)(object?)e.Nrg == salesForm.SetterNrg)
.OrderByDescending(e => e.EmployeeId)
.FirstOrDefaultAsync();
}
else if (salesForm.CsTransferCategory == "CSR Team (Philippines)")
{
var toCheck = $".{salesForm.SetterNrg}#aaa-bbb.com";
setterEmployee = await context3.Employees
.Where(e => e.Nrg == null && e.AzureAccountEnabled == 1
&& e.AzureEmail.EndsWith(toCheck))
.OrderByDescending(e => e.EmployeeId)
.FirstOrDefaultAsync();
}
if (setterEmployee != null)
{
salesForm.SetterAgentFullName = setterEmployee.AzureFullName;
salesForm.SetterJobTitle = setterEmployee.AzureRole;
salesForm.SetterEmail = setterEmployee.AzureEmail;
salesForm.SetterTeam = setterEmployee.AzureTeam;
}
}
context3.SalesForms.Add(salesForm);
await context3.SaveChangesAsync();
}
The problem is in e.AzureEmail.Contains("#aaa-bbb.com"), there is no equivalent in sql to this. Try EF.Functions.Like(e.AzureEmail, "%#aaa-bbb.com%"). Everything from your expression will work if you materialize your data with .ToList() or something and perform it on the client, but it is extremely inefficient.

The entity type 'EntityQueryable<Entrys>' was not found. Ensure that the entity type has been added to the model

I have a scenario, I have users submitting entries to an API endpoint and a flag is updated as 1 on the database. A user can submit more than entry as per there feel and need per time. I have a logic that checks if an entry already exists, and if a user submits another form, the previous form is set to 0 and the new form is set to 1. Whenever I submit a second entry I end up with an error
The entity type 'EntityQueryable' was not found. Ensure that
the entity type has been added to the model. at
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.GetOrCreateEntry(Object
entity)
this is my logic for checking
public async Task<Entrys> AddEntrys(Entrys entrys)
{
var pastSurveys = _context.Entrys.Where(e => e.UpdatedBy == entrys.UpdatedBy && e.Month == entrys.Month
&& e.Day == entrys.Day && e.Year == entrys.Year && e.CurrentStatus==true).AsQueryable();
if (pastSurveys.Count() > 0)
{
foreach (Entrys e in pastSurveys)
{
if (e.CurrentStatus == true)
{
e.CurrentStatus = false;
}
}
_context.Add(pastSurveys);
_context.SaveChanges();
}
entrys.Id = Guid.NewGuid().ToString();
_context.Add(entrys);
_context.SaveChanges();
return entrys;
}
How can I have my logic to keep on checking the existing surveys and updating them to 0 while new ones are set to 1 without getting the error above, Have tried researching no luck do far. Thank you in advance
Problem that instead of Updating entities you inserts them. Also you do not need two SaveChanges calls. pastSurveys.Count() also executes unwanted query.
Corrected method:
public async Task<Entrys> AddEntrys(Entrys entrys)
{
var pastSurveys = _context.Entrys
.Where(e => e.UpdatedBy == entrys.UpdatedBy && e.Month == entrys.Month
&& e.Day == entrys.Day && e.Year == entrys.Year && e.CurrentStatus == true)
.ToList();
foreach (Entrys e in pastSurveys)
{
e.CurrentStatus = false;
}
entrys.Id = Guid.NewGuid().ToString();
_context.Add(entrys);
_context.SaveChanges();
return entrys;
}
Hi #arrif from your implementation
change the _context.Add(pastSurveys); to _context.UpdateRange(pastSurveys);
From your current setup you adding instead of updating the flag. Try that and tell if it works cheers

Filtering data with multiple filter values

Hello fellow stackoverflowers,
I'm currently working on a project which gives me a bit of trouble concerning filtering data from a database by using multiple filter values. The filter happens after selecting the filters and by clicking a button.
I have 5 filters: Region, Company, Price, and 2 boolean values
Note that Region and Company are special dropdownlist with checkboxes which means the user can select one or more regions and company names.
I already made a few tests and came up with a incomplete code which works a bit but not to my liking.
Problems arise when one of my filters is NULL or empty. I don't really know how to process this. The only way i thought of was using a bunch of IF ELSE statements, but i'm starting to think that this will never end since there are so much possibilities...
I'm sure there is a far more easier way of doing this without using a bunch of IF ELSE statements, but i don't really know how to do it. If anyone could steer me in the right direction that would be appreciated. Thanks
Here is what i have right now (I haven't added the Price to the query for now):
protected void filterRepeater(List<int> regionIDs, string[] companyArray,
string blocFiltValue, bool bMutFunds, bool bFinancing)
{
DatabaseEntities db = new DatabaseEntities();
PagedDataSource pagedDsource = new PagedDataSource();
IQueryable<Blocs> query = (from q in db.Blocs
where q.isActive == true
orderby q.date descending
select q);
IQueryable<Blocs> queryResult = null;
//if some filters are NULL or Empty, it create a null queryResult
queryResult = query.Where(p => companyArray.Contains(p.company) &&
regionIDs.Contains((int)p.fkRegionID) &&
(bool)p.mutual_funds == bMutFunds &&
(bool)p.financing == bFinancing);
if (queryResult.Count() > 0)
{
//Bind new data to repeater
pagedDsource.DataSource = queryResult.ToArray();
blocRepeater.DataSource = pagedDsource;
blocRepeater.DataBind();
}
}
Only add the relevant filters to query:
IQueryable<Blocs> query =
from q in db.Blocs
where q.isActive == true
orderby q.date descending
select q;
if (companyArray != null)
{
query = query.Where(p => companyArray.Contains(p.company));
}
if (regionIDs != null)
{
query = query.Where(p => regionIDs.Contains((int)p.fkRegionID));
}
// ...
// etc
// ...
if (query.Any()) // Any() is more efficient than Count()
{
//Bind new data to repeater
pagedDsource.DataSource = query.ToArray();
blocRepeater.DataSource = pagedDsource;
blocRepeater.DataBind();
}
If you want to filter only by the filter values that are not null or empty then you can construct the query by appending the where clauses one by one:
if(companyArray != null && companyArray.Length > 0) {
query = query.Where(p => companyArray.Contains(p.company));
}
if(regionIDs!= null && regionIDs.Length > 0) {
query = query.Where(p => regionIDs.Contains((int)p.fkRegionID));
}
if (!String.IsNullOrEmpty(blocFiltValue)) {
query = query.Where(p => p.Block == blocFiltValue);
}
Also you can use nullable values for value types, if you need to filter them optionally
bool? bMutFunds = ...; // Possible values: null, false, true.
...
if(bMutFunds.HasValue) {
query = query.Where(p => (bool)p.mutual_funds == bMutFunds.Value);
}
Maybe you can create a string for the SQL sentence, and dynamically add parts to this sentence like if something was selected or checked you add something to this string when thh selection was completed by the user you can execute this SQL sentence.

How can I get multiple data?

I can show just one customer, I know the problem is because I use FirstOrDefault in my LINQ.
How can get another customer? I still don't understand the concept of IQueryable or IEnumerable.
public int getNota(DateTime dt, int lap)
{
DataClassesPelleDataContext myDb = new DataClassesPelleDataContext();
var nota = (from u in myDb.TBL_TRANSAKSI_SEWA_LAPANGAN_REGULERs
where u.TGL_PEMAKAIAN.Value.Date == dt.Date && u.ID_LAPANGAN == lap
select u.ID_SEWA).FirstOrDefault();
return nota;
}
I dont know for sure what you are trying to achive
But you can use
var notasIds = yDb.TBL_TRANSAKSI_SEWA_LAPANGAN_REGULERs
.Where(u => u.TGL_PEMAKAIAN.Value.Date == dt.Date && u.ID_LAPANGAN == lap)
.Select(n => n.ID_SEWA)
.ToList();
and then loop over the notas with
foreach (var sewaId in notasIds)
{
// to logic here
}
You can also comment .Select() call and get whole objects.
Regars

WHERE IN clause

I'm working in MVC3 project. I was browsing for a while and trying several examples but I could not get it working.
I need to get a list of record from OrderForm table whose DeptID are in another list I already have got.
I'm aware that I need to use Contains() replacing IN SQL clause, but every example that I could read are doing this in the same way
.Where(ListOfDepartments.Contains(q.DeptID))
This is my method at the controller, which obviously is not working:
public ActionResult ValidOrders(string installation, string orderpriority, string stockclass, string validity)
{
int instID = System.Convert.ToInt32(installation);
int orderpriorityID = System.Convert.ToInt32(orderpriority);
int stockclassID = System.Convert.ToInt32(stockclass);
string period = validity;
try
{
var departments = dba.Department
.Where (a => a.InstID == instID);
var valid = dba.OrderForm
.Where(q => q.FormType == 3
&& q.FormStatus == 2
&& q.OrderPriority.OrderPriorityID == orderpriorityID
&& q.StockClassID == stockclassID
&& departments.Contains(q.DeptID));
return View(valid.ToList());
}
catch (Exception)
{
return View("Error");
}
}
What I'm doing wrong?
you need a list of int, not Department.
var departments = dba.Department
.Where (a => a.InstID == instID)
.Select(d => d.Id);//Id is a guess, it maybe another property name
//.ToList();

Categories