As my code is taking long time to process. I analyzed the code & searched the part of the code which is taking lots of time.
In my listTempInOut there are over 100000 records. SDetails also have more records. I wanted to update 2 fields in the model. So following is the code :-
var dataUpd = (from A in tempSS
from B in SDetails
from C in listTempInOut
where A.Id == B.Id
&& A.Shift == B.Shift && A.Employee == C.Employee && A.SDate == C.Time_Date1
select new { A.SId, B.Status, C }).ToList();
foreach (var row in dataUpd)
{
row.C.Time_Field1 = row.ShiftId;
row.C.Time_Field2 = row.Status.ToString();
}
What change can i do in the above code to improve the performance so that it takes less time to execute the code.
Updates in the entity framework can be very slow, try setting the AutoDetectChangesEnabled property to false in your context (see code below, I'm not sure what your context is actually called so I called it "myContext"). You must remember to set it back to true when you are done with your updates so I'd recommend wrapping your code in a try/finally block.
try
{
myContext.Configuration.AutoDetectChangesEnabled = false;
var dataUpd = (from A in tempSS
from B in SDetails
from C in listTempInOut
where A.Id == B.Id
&& A.Shift == B.Shift && A.Employee == C.Employee && A.SDate == C.Time_Date1
select new { A.SId, B.Status, C }).ToList();
foreach (var row in dataUpd)
{
row.C.Time_Field1 = row.ShiftId;
row.C.Time_Field2 = row.Status.ToString();
}
}
finally
{
myContext.Configuration.AutoDetectChangesEnabled = true;
}
Related
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();
}
I am trying to identify if a record exists in three tables.
TableMapping:
RbMapping:
RgMapping:
I am using EF 7 dbContext to access these tables.
I have written two samples of LINQ but not sure if it will perform against large volume of data.
Method 1:
bool isExist = dbContext.MappingTable
.AsNoTracking()
.Where(x => x.mappingCode == 1234)
.Any(x => x.RbMappings.Any(y => y.MappingId == x.MappingId && y.RbId == 3)
&& x.RgMapping.Any(z=> z.MappingId == x.MappingId && z.RgId == 2);
Method 2:
bool IsExist = (from mp in dbContext.MappingTable
join rb in dbContext.RbMapping on new
{
JoinProperty1 = mp.MappingId,
JoinProperty2 = rbId // Will be input field = 3
}
equals new
{
JoinProperty1 = rb.MappingId,,
JoinProperty2 = rb.RbId
}
join rg in dbCContext.RgMappings on new
{
JoinProperty1 = rb.MappingId,
}
equals new
{
JoinProperty1 = rb.MappingId,
}
where hs.MappingCode == 1234
select mp).AnyAsync();
Can anyone advise which one will work better for large volumes of data? I'll be running these Linq queries several times.
And these tables are also huge around 4 million records.
I use queries in EF4 to pull back records and process information through various other means (not EF) based on the data within, so I frequently have detached EF objects in lists.
In this case, I have a query in EntityFramework 4.0 that is not loading a related entity, even though I am using the .Include("...") method.
using (MyDBEntities ctx = new MyDBEntities())
{
ctx.ContextOptions.LazyLoadingEnabled = false;
// Get the first X records that need to be processed
var q = (from t in ctx.DBTables
.Include("Customer")
let c = t.Customer
where t.statusID == (int)Enums.Status.PostProcessing
&& c.isActive == true
select t
).Take(batchSize).ToList();
foreach (DBTable t in q)
{
// this results in c == null
Customer c = t.Customer;
// However t.CustomerID has a value, thus I know
// that t links to a real Customer record
Console.WriteLine(t.CustomerID);
}
}
Can anyone help me understand why Customer is not loading, even though I am explicitly stating to include it?
I found the root of the issue! The demon lies in the "let" command. Whenever I have a let, or a second "from" clause (like a join), then the ".Includes" get ignored!!!
// -- THIS FAILS TO RETRIEVE CUSTOMER
// Get the first X records that need to be processed
var q = (from t in ctx.DBTables
.Include("Customer")
// Using a "let" like this or
let c = t.Customer
// a "from" like this immediately causes my include to be ignored.
from ca in c.CustomerAddresses
where t.statusID == (int)Enums.Status.PostProcessing
&& c.isActive == true
&& ca.ValidAddress == true
select t
).Take(batchSize).ToList();
However, I can go get the ID's that I need to fetch in one call, then have a second "go get my includes" call, and everything works just fine.
// Get the first X record IDs that need to be processed
var q = (from t in ctx.DBTables
let c = t.Customer
from ca in c.CustomerAddresses
where t.statusID == (int)Enums.Status.PostProcessing
&& c.isActive == true
&& ca.ValidAddress == true
select t.TableID
).Take(batchSize).ToList();
// Now... go "deep-load" the records I need by ID
var ret = (from t in ctx.DBTables
.Include("Customer")
where q.Contains(t.TableID)
select t);
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();
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();
}