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();
}
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 want to know how many people are in a especify local, using entry and exit validation of this person. If he has entered in the local, then he will generate a transaction with a TrCode = "C0". when he comes out of the place, he will generate a TrCode = "CI". There are other types of TrCode, but it is useless for this kind o validation. i have a query that returns to me this result down bellow:
var query = from a in context.CardDB
join c in context.tblTransaction on a.CardNo equals c.CardNo
where c.TrCode == "C0" || c.TrCode == "CI"
where c.TrSiteCode == sitecode
select c;
Now I have all the rows that have the TrCode == "C0" or TrCode == "CI". But the result gives me all the transactions that the employers(CardDB) did. So the result gives a lot of transactions made of different employers. Sometimes some employer make 2 or even 3 transcations like, when he arrives and when he goes out for lunch, then he cames back etc.
I have to show in a grid just the employers that have in general count more transactions TrCode == "C0" than TrCode == "CI". So, what i have to do to count the transcations of only the employers with the same ID, and, when showing it in the grid, show just a row of this employers and not all the rows.
Since already, Thank you!
var queryNumberC0 = query.Where(c => c.TrCode == "C0").Select(c => c.ID).GroupBy(c => c.Value).ToList();
var queryNumberC1 = query.Where(c => c.TrCode == "C1").Select(c => c.ID).GroupBy(c => c.Value).ToList();
And to get the number of the ID y (Key is the ID of the customer):
int y = [Customer's ID];
int temp = queryNumberC0.Find(c => c.Key == y);
You don't have to specifie the ToList() at the end of the query, do what you want with the result. I just find it easier to browse
My model has:
Several DeviceStatus attached to one mandatory Device
SeveralDevice attached to one mandatory Panel
When I query DeviceStatus, I need to have Device and Panel attached to it in the query result.
... DeviceStatus.Device is null in the query result.
Here is the Linq Query:
using (var actiContext = new ActigraphyContext())
{
var todayStatus =
from s in actiContext.DeviceStatus.Include(s1 => s1.Device.Panel)
where DbFunctions.TruncateTime(s.TimeStamp) == DbFunctions.TruncateTime( DateTimeOffset.Now)
&& s.Device.Panel.Mac == mac
&& (s.Device.Ty == 4 || s.Device.Ty == 9)
select s;
// var tempList = todayStatus.toList();
var todayLastStatus =
from s in todayStatus.Include(s1 => s1.Device.Panel)
let lastTimeStamp = todayStatus.Max(s1 => s1.TimeStamp)
where s.TimeStamp == lastTimeStamp
select s;
var requestResult = todayLastStatus.FirstOrDefault();
return requestResult;
}
If I uncomment the line // var tempList = todayStatus.toList();, where tempList is not used, it works: requestResult.Device is set!
But the bad side is todayStatus.toList triggers a request that brings a huge amount of data.
So how to get the DeviceStatus with its relative objects ?
Note: the database behind is SQL Server 2012
When you call an Include() over a LINQ query, it performs Eagerly Loading.
As documented in MSDN:
Eager loading is the process whereby a query for one type of entity also loads related entities as part of the query. Eager loading is achieved by use of the Include method.
When the entity is read, related data is retrieved along with it. This typically results in a single join query that retrieves all of the data that's needed. You specify eager loading by using the Include method.
So you need to call the .toList() to complete the query execution.
Since the data is huge, you can pickup relative specific columns as per your requirement by using the Select clause.
var todayStatus =
from s in actiContext.DeviceStatus
.Include(s1 => s1.Device.Panel.Select(d => new
{
d.DeviceId,
d.DeviceName,
d.PanelID
}))
where DbFunctions.TruncateTime(s.TimeStamp) == DbFunctions.TruncateTime( DateTimeOffset.Now)
&& s.Device.Panel.Mac == mac
&& (s.Device.Ty == 4 || s.Device.Ty == 9)
select s;
var tempList = todayStatus.toList();
The query doesn't actually run until you do a call like ToList(), which is why uncommenting that line works. If the query is bringing back too much data, then you need to change the query to narrow down the amount of data you're bringing back.
Ok this request is a more simple way to achieve this:
using (var actiContext = new ActigraphyContext())
{
var todayLastStatus =
from s in actiContext.DeviceStatus.Include(s1 => s1.Device.Panel)
where DbFunctions.TruncateTime(s.TimeStamp) == DbFunctions.TruncateTime( DateTimeOffset.Now)
&& s.Device.Panel.Mac == mac
&& (s.Device.Ty == 4 || s.Device.Ty == 9)
orderby s.TimeStamp descending
select s;
var requestResult = todayLastStatus.Take(1).FirstOrDefault();
return requestResult;
}
But the question remains: why didn't I get the relative object in my first request ?
i have the following code:
int selectedcourseId = Convert.ToInt32(c1.Text);
var cid = (from g in re.Sections where g.CourseID == selectedcourseId select g.CourseID);
int selectedinstructorid = Convert.ToInt32(c2.Text);
var iid = (from u in re.Sections where u.InstructorID == selectedinstructorid select u.InstructorID);
i want to compare the two (selectedcourseId) with (cid) and (selectedinstructorid) with (iid) in if-statement such as:
if (selectedcourseId = cid && selectedinstructorid = iid)
{
MessageBox.Show("it already exists");
}
i have tried many things that didnt work our because i have limited knowledge.
thank you very much in advance for any comment or answer
You can change your code as: (but it is meaningless for your situation to check this)
if (selectedcourseId == cid.First() && selectedinstructorid == iid.First())
First of all for checking equality in if statement you must use ==, not =. And the second is the IQueryable<T> allows you to execute a query against a specific data source, but it uses deferred execution. For executing it in your case, you can use First().
But, I suggest that you are just learning how to use LINQ and therefore you have written this code.
I don't know what you are trying to achive. But, if you want to search if there is any result with that ID's, the you must use Any():
var result1 = from g in re.Sections where g.CourseID == selectedcourseId select g.CourseID;
var result2 = from u in re.Sections where u.InstructorID == selectedinstructorid select u.InstructorID;
if(result1.Any() && result2.Any()) { ... }
Or, if you want to find if there is any row which has specified CourseID and InstructorID, then you can call one Any():
if(re.Sections.Any(x => x.CourseID == selectedcourseId && x.InstructorID == selectedinstructorid))
{ ... }
Let me try to find the X from this XY-problem. I guess you want to check if there is already a combination of courseid + instructorid. Then use a single query:
var data = from section in re.Sections
where section.InstructorID == selectedinstructorid
&& section.CourseID == selectedcourseId
select section;
if(data.Any())
{
MessageBox.Show("it already exists");
}
You should not do it in two queries, because the two results might be related to two different rows. This would lead to "false positives" when an instructor handles some section, and a course has some instructors, but the two matches do not belong to the same row:
course instructor
------ ----------
100 10
101 15
102 20
If you are looking for a combination (101, 10) it is not enough to see that 100 is present and 10 is present; you need to check that the two belong to the same row in order to consider it a duplicate.
You can fix this by making a "check presence" query, like this:
var existing = re.Sections
.Any(s => s.InstructorID == selectedinstructorid && s.CourseID == selectedcourseId);
if (existing) {
MessageBox.Show("it already exists");
}
if (selectedcourseId = cid && selectedinstructorid = iid)
this will not work, since single '=' is an assignment, not a comparation (which is '==')
also, you can try to do something like this
var cid = (int)((from g in re.Sections where g.CourseID == selectedcourseId select g.CourseID).FirstOrDefault());
so you select the first or default record from your list and cast it to int
I have a workflow table that takes all the steps of a process. Lets work with 2 of those statuses:
Saved (new item saved but not submitted yet)
Submitted (item submitted for review)
Now I want to create a BatchSumbit function that will submit all the unsubmitted items. For this I need to query for all the items which has a latest workflow status of "Saved". All the historical workflow entries for the item still exist and it can go from "Submitted" back to "Saved" a few times.
Here is the table structure:
Now i want a linq query that will give me what I require:
from wasteInformation in wasteDB.WasteInformations
join workFlowHistory in wasteDB.WorkFlowHistories on wasteInformation.WasteInformationId equals workFlowHistory.WasteInformationId
// Join with last instance in workflow table (where workflowHistory.DateAdded is greatest)
where workFlowHistory.WorkFlowStep == "Saved"
&& wasteInformation.WasteProgrammeId == captureModel.WasteProgrammeId
&& wasteInformation.WasteSourceId == captureModel.WasteSourceId
select new
{
WasteInformationId = wasteInformation.WasteInformationId,
FinancialQuarter = wasteInformation.FinancialQuarter,
FinancialYear = wasteInformation.FinancialYear,
WasteProgrammeId = wasteInformation.WasteProgrammeId,
WasteMonth = wasteInformation.WasteMonth,
WasteYear = wasteInformation.WasteYear,
DateCaptured = wasteInformation.DateCaptured,
WasteSourceId = wasteInformation.WasteSourceId,
WasteDate = wasteInformation.WasteDate
}
The query as it is will give be all the saved entries for the item. I want it to give me the item if that item's last entry has a WorkFlowStep of "Saved"
Edit:
I've got something that looks like it works. Still need to test it some more:
var SavedWasteInformation = wasteDB.WasteInformations.Where(wi => wi.WorkFlowHistories.FirstOrDefault(wf => wf.DateAdded == wi.WorkFlowHistories.Max(wf_in => wf_in.DateAdded)).WorkFlowStep == "Saved"
&& wi.WasteProgrammeId == captureModel.WasteProgrammeId
&& wi.WasteSourceId == captureModel.WasteSourceId);
Edit:
My solution above and Vladimirs's below both seem to work, but after inspecting the execution plans Vladimirs's looks like the better option:
Providing that you have collection of WorkFlowHistories on your WasteInformation I believe that query will select WasteInformations with their latest WorkFlowHistory (if any):
from wasteInformation in wasteDB.WasteInformations
where wasteInformation.WasteProgrammeId == captureModel.WasteProgrammeId
&& wasteInformation.WasteSourceId == captureModel.WasteSourceId
select new
{
WasteInformation = wasteInformation,
LastSavedWorkFlowHistory = wasteInformation.WorkFlowHistories
.Where(x => x.WorkFlowStep == "Saved")
.OrderByDescending(x => x.DateAdded)
.FirstOrDefalt()
}