DELETE From Table
WHERE ID in (1,2,3, ... )
Is there any way to produce following query in LINQ? I tried RemoveRange, but from SQL Server Profiler find that it actually deletes records separately
You could first define the item(s) to remove, then iterate over the list removing them one by one: (note that the whole operation has to be done inside database context scope otherwise it won't work)
var toRemove = list.Where(l => l.id == 1 || l.id == 2 || l.id == 3);
foreach (var item in toRemove)
{
databasecontext.table.Remove(item); //replace databasecontext.table with your own context and table name
}
You can write it in single line
table.RemoveAll(tbl => tbl.id == 1 || tbl.id == 2 || tbl.id == 3);
Hope this helps.
Try this piece of code to make this, It will work for you.
DataContextClass _DbContext = new DataContextClass();
var remove = _DbContext.tableName.where(x=>x.id >= 1 && x.id <= endValue);
if(remove != null)
{
db.logins.RemoveRange(remove);
db.SaveChanges();
}
Related
I have this scenario in which i query with FindByMany (which takes the lambda and returns post if user country and category matches, (as seen in the "else")
But now i need to customize the return with prefered subcategories from users, so what im doing is query n times foreach subcategory and just addRange. I dont want to query 5 times the db if the user has 5 subcategories as favorite, but i dont know how to apply a dinamic OR.
So my question is, how can this code be improved for performance.
var posts = new List<Content>();
if (request.UserId != 0)
{
var user = _userRepository.FindBy(u => u.Id == request.UserId);
if (user != null && user.SubCategories.Any())
{
foreach (var temp in user.SubCategories.Select(subCategory => _contentRepository.FindManyBy(
c =>
c.Country.Id == country.Id && c.Category.Id == theCategory.Id &&
c.SubCategory.Id == subCategory.Id).ToList()))
{
posts.AddRange(temp);
}
}
}
else
{
posts = _contentRepository.FindManyBy(
c => c.Country.Id == country.Id && c.Category.Id == theCategory.Id
).ToList();
}
Could you not just materalise the sub-categories into a list, and then in your FindBy use a thatlist.Contains()?
You can get the user's sub-categories with one query and then use the list and the Contains method to filter the relevant posts. Contains method is supported by most LINQ query provides and should be translated into a single database query.
var subcategories = user.SubCategories.ToList();
foreach (var temp in _contentRepository.FindManyBy(
c =>
c.Country.Id == country.Id && c.Category.Id == theCategory.Id &&
subcategories.Contains( subCategory.Id ) ).ToList()))
{
posts.AddRange(temp);
}
You can build expression for where clause using Expression.OrElse or use enter link description here
The core of the problem is that you're forcing query execution for each item instead of dynamically building the query. #Milney has the right idea; example code below.
IEnumerable<int> subCategoryIds = user.SubCategories.Select(x => x.Id);
var posts = _contentRepository.FindByMany(c => c.Country.Id == country.Id
&& c.Category.Id == theCategory.Id
&& subCategoryIds.Contains(c.SubCategoryId)).ToList();
I added data to an ObservableCollection from a LINQ query:
foreach (var item in test4)
{
lstPareto.Add(new clsPareto(Convert.ToInt32(item.Step), Convert.ToInt32(item.LogID), test3.Where(p => p.Step.Equals(item.Step) && p.LogID.Equals(item.LogID)).Count()));
}
And this works fine. I get the items I want and convert them to an int when adding them to the list.
Then I have the following queries that pulls data from multiple databases:
int intCmbTestNr = Convert.ToInt32(m_strCmbTestNrSelectedItem);
var productIndex = (from x in m_dcSQL_ConnectionProdTest.DC3_VersionReleases
where x.TestNumber.Equals(intCmbTestNr)
select x.ProductIndex).First();
var version = ((from y in m_dcSQL_ConnectionProdTest.DC3_MainSetups
where y.ProductIndex == productIndex && y.SubVersion == 0
select y.Version).Max());
var versionIndex = (from z in m_dcSQL_ConnectionProdTest.DC3_MainSetups
where z.ProductIndex == productIndex && z.Version.Equals(version) && z.SubVersion == 0
select z.VersionIndex).First();
var subFuncName = from a in m_dcSQL_ConnectionProdTest.DC3_SubFunctions
where a.VersionIndex == versionIndex && a.FunctionNumber == lstPareto.Select(b => b.intStep) && a.SubFunctionNumber == lstPareto.Select(c => c.intStep)
select a.SubFunctionName;
Consider subFuncName. What I am trying to achieve here is to compare a.FunctionNumber to intStep and a.SubFunctionNumber to intLogID of the list lstPareto. However, it says the following: "Operator '==' cannot be applied to operands of type'int' and 'System.Collections.Generic.IEnumerable". I think I know the reason for this, seeing as I'm trying to compare a single int to a whole collection. But how do I compare to every single item intStep and intLogID of the list? I cannot seem to wrap my head around this. Do I use a foreach loop somewhere? Can somebody get me back on track?
Sorry if the title is somewhat vague, couldn't really think of a good one.
If both FunctionNumber and SubFunctionNumber is int:s. Then you can change the condition to this:
lstPareto.Select(b => b.intStep).Contains(a.FunctionNumber)
&& lstPareto.Select(c => c.intStep).Contains(a.SubFunctionNumber)
Update
The reason is most probably because you do not have .ToList(), .First(), .Single() in the query. Depends a little bit what you expect. You could change it to this:
var subFuncName = (from a in m_dcSQL_ConnectionProdTest.DC3_SubFunctions
where a.VersionIndex == versionIndex && lstPareto.Select(b => b.intStep).Contains(a.FunctionNumber)
&& lstPareto.Select(c => c.intStep).Contains(a.SubFunctionNumber)
select a.SubFunctionName).ToList();
Reference:
Enumerable.Contains Method
I am trying to condense my code by avoiding multiple foreach loops to accomplish this task. I have a listbox that is populated by Table A. I need to compare those values with Table B to populate another list.
Table A has a 1 to many relationship with Table B and while my solution worked for the time being, it is using quite a bit of memory so I need to condense it.
List<int> listProj = new List<int>();
var _tableB = from t in TableB
where t.StatID == 1 || t.StatID == 2
select p.ID;
var _tableA = from ListItem n in lstTableA.Items
where _tableB.Contains(int.Parse(n.Value)) && n.Selected == true
select n;
foreach (ListItem i in _tableA)
{
int affID = Convert.ToInt32(i.Value);
if (TableB.Where(t => t.ID == affID && t.StatID == 1 || t.StatID == 2).Any()
{
foreach(var item in TableB.Where(t => t.ID == affID && t.StatID == 1 || t.StatID == 2)
{
int pID = Convert.ToInt32(item.pID);
listProject.Add(projID);
}
}
}
The main problem is that these two loops are looping through quite a bit of records which is causing a memory leak. I feel that there is a way to grab many records at once and add them to the list, hence the one to many relationship between Table A and Table B.
I think this would give you the same result as the whole code above unless I'm making a mistake on the logic of your program.
This would return the project ids:
List<int> listProj = (from t in TableB
where (from n in lstTableA.Items.Cast<ListItem>().ToList()
where n.Selected == true
select n).Any(g => int.Parse(g.Value) == t.ID)
&& (t.StatID == 1 || t.StatID == 2)
select t.pID).ToList();
Considere this piece of code in LINQ (please focus on var list2):
var list1 = ....... /* This linq doesnt matter. Just for clarify that it is used in the below linq */
var list2 = dba.OrderForm
.Where(q => q.OrderPriority.OrderPriorityID == orderpriorityID
&& q.StockClass.StockClassID == stockclassID
&& dba.AuditTrailLog.Where(log => q.OrderID == log.ObjectID)
.Any(log => log.ColumnInfoID == 486
&& log.OldValue == "2"
&& log.NewValue == "3")
&& dba.AuditTrailLog.Where(log2 => q.OrderID == log2.ObjectID)
.Any(log2 => log2.ColumnInfoID == 487
&& log2.OldValue == "1"
&& log2.NewValue == "2")
&& lista.Contains(q.OrderID));
This way I have in list2 a list of records that belongs to OrderForm model. I need to pass it to another model called ViewResult:
What I need is to get the variable log2.ModificationDate that belongs to AuditTrailLog table but it is not included on OrderForm Model
List<ViewResult> vr = new List<ViewResult>();
foreach (OrderForm o in list2)
{
ViewResult r = new ViewResult();
r.NumOrden = o.FormNo;
r.Title = o.Title;
r.Com = o.OrderPriority.Descr;
r.OClass = o.StockClass.Descr;
r.RodT = /* <<------ Here is where I need to assign log2.ModificationDate
vr.Add(r);
}
Thanks.
What I understand is AuditTrailLog relation is null while you are getting data. And you want to fill it with related data.
You must Include this table like:
(That means you are doing join on sql)
var list2 = dba.OrderForm.Include("AuditTrailLog")...
It is important the relation between them. "One to many" or "many to one". Use AuditTrailLog or AuditTrailLogs according to your relation.
So, if I use this query directly or by using db.ExecuteCommand() , everything will work fine;
update Market..Area set EndDate = NULL where ID = 666 and NID =1 and Code = 36003
However, I cant seem to do this in LINQ to SQL, I've tried a few different methods that all seem like they should work, here is an example of one:
var s= db.Area.Single(s => s.ID == 666 && s.Code == 36003 && s.NID == 1);
s.EndDate = null;
db.SubmitChanges();
I dont know what else to try to get this working.
EDIT
I am only trying to edit ONE item
Is there a primary key defined on the Area table?
Linq 2 SQL will not make an update to a table without a primary key defined. (And, as far as I can remember, it will fail silently).
Do you want update more than one item? Even not you can write something like:
IQueryable<Area> iArea =
from s in db.Area
where s.ID == 666 && s.Code == 36003 && s.NID == 1
select s;
iArea.ToList().ForEach(item => { item.EndDate = null; });
db.SubmitChanges();
There is no built in method for doing batch updates. But you can pick some batch extensions from this blog.
Your syntax appears to be correct. The only other thing I can think of which would be causing the failure is if you are trying to do multiple updates within the same data context. Try this:
using (DataContext db = new DataContext())
{
var s = db.Area.Single(s => s.ID == 666 && s.Code == 36003 && s.NID == 1);
s.EndDate = null;
db.SubmitChanges();
}