SQL SELECT COMMAND WITH JOIN in C# - c#

CourseRepeater cr = new CourseRepeater();
List<CourseRepeater> course = new List<CourseRepeater>();
string sql = "SELECT u.Name, u.Surname, c.Name, c.ClosingDate, c.BeginDate FROM Course AS c, JOIN Users AS u on u.UserID=c.UserID";
DataTable dt = DataBase.SQLSelect(sql);
if (dt.Rows.Count != 0)
{
cr.Name = dt.Rows[0]["Name"].ToString(); // ?
}
I have Database class that contains SQLSelect().Here there is not problem.
My question is so : If I want to get Users.Name, dt.Rows[0]["Name"] in this row ,I should write dt.Rows[0]["Name"] or dt.Rows[0]["u.Name"] ?

Might as well move the comment to the answer.
You should alias the fields in the query.
The other option are more fragile or not as clear.
SELECT u.Name UsersName, c.Name CourseName FROM...

Related

Need help ServiceStack OrmLite how to Update table with Multiple Join table Entity Framework C#

I need the servicestack experts help regarding Servicestack Update query with join multiple tables in C#. I have googled and gone through all the related documents and site but not able to find enough details regarding Update with Join query.
I would like to update the One table with join the three different table and where clause. I have tried all the ways by entity framework but not able to do it. I can do it by Db.ExecuteSql(SqlQuery) but I would like to do it by Entity Framework. My query as below .
I want to update the UpdateStatus of HeartRate Table join with PatientDetails, DeviceSession, PatientSession and HeartRate tables and where clause is HeartRate.timestamp = ‘#starttime’ and PatientId = ‘#PatientId’
SqlQuery =
UPDATE HeartRate SET UpdateStatus = 1
WHERE HeartRateID IN ( SELECT hr.HeartRateID
FROM PatientDetails pd join PatientSession ps on pd.PatientDetailsId = ps.ByPatientId
join DeviceSession ds on ps.PatientSessionId = ds.ByPatientSessionId join HeartRate hr on ds.DeviceSessionID = hr.ByDevSessionID
WHERE
pd.PatientId = '#PatientId'
AND
hr.Timestamp = '#starttime'
order by hr.Timestamp Asc )
I need something like below
(Its wrong and incomplete).
Db.UpdateOnly(
new HeartRate { UpdateStatus = 1 },
ps => new { ps.UpdateStatus },
.SqlJoinBuilder<DeviceSession, PatientSession>((ds2, ps) => ds2.ByPatientSessionId == ps.PatientSessionId)
.Join<PatientSession, PatientDetails>((ps2, pd) => ps2.ByPatientId == pd.PatientDetailsId)
.Where<HeartRate, PatientDetails>((lthr2, pd2) => (lthr2.Timestamp == #starttime) && pd2.PatientId == PatientId)
.OrderBy(lthr2 => lthr2.Timestamp));
Please help me out.
Thanks
Susheel
//Try this one
var model = from v in Db.HeartRate
where
(
from pd in Db.PatientDetails
join ps in Db.PatientSession on pd.PatientDetailsId equals ps.ByPatientId
join ds in Db.DeviceSession on ps.PatientSessionId equals ds.ByPatientSessionId
join hr in Db.HeartRate on ds.DeviceSessionID equals hr.ByDevSessionID
where pd.PatientId == PatientId && hr.Timestamp == starttime
select new { HeartRateID = hr.HeartRateID }
).ToList().Contains(v.HeartRateID)
select v;
foreach (var item in model)
{
item.UpdateStatus = 1;
Db.SaveChanges();
}

left join in Linq query

I'm trying to do a left join, not an inner join in a linq query. I have found answers related to using DefaultIfEmpty() however I can't seem to make it work. The following is the linq query:
from a in dc.Table1
join e in dc.Table2 on a.Table1_id equals e.Table2_id
where a.Table1_id == id
orderby a.sort descending
group e by new
{
a.Field1,
a.Field2
} into ga
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects = (from g in ga select new SubObject{
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
The query only gives me the rows from table 1 that have a corresponding record in table 2. I would like every record in table 1 populated into MyObject and a list of 0-n corresponding records listed in manySubObjects for each MyObject.
UPDATE:
I tried the answer to the question that is a "possible duplicate", mentioned below. I now have the following code that does give me one record for each item in Table1 even if there is no Table2 record.
from a in dc.Table1
join e in dc.Table2 on a.Table1_id equals e.Table2_id into j1
from j2 in j1.DefaultIfEmpty()
where a.Table1_id == id
orderby a.sort descending
group j2 by new
{
a.Field1,
a.Field2
} into ga
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects = (from g in ga select new SubObject{
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
However, with this code, when there is no record in table2 I get "manySubObject" as a list with one "SubObject" in it with all null values for the properties of "SubObject". What I really want is "manySubObjects" to be null if there is no values in table2.
In reply to your update, to create the null listing, you can do a ternary in your assignment of manySubObjects.
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects =
(from g in ga select g).FirstOrDefaut() == null ? null :
(from g in ga select new SubObject {
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
Here is a dotnetfiddle that tries to do what you're attempting. https://dotnetfiddle.net/kGJVjE
Here is a subsequent dotnetfiddle based on your comments. https://dotnetfiddle.net/h2xd9O
In reply to your comments, the above works with Linq to Objects but NOT with Linq to SQL. Linq to SQL will complain that it, "Could not translate expression ... into SQL and could not treat as a local expression." That's because Linq cannot translate the custom new SubObject constructor into SQL. To do that, you have to write more code to support translation into SQL. See Custom Method in LINQ to SQL query and this article.
I think we've sufficiently answered your original question about left joins. Consider asking a new question about using custom methods/constructors in Linq to SQL queries.
I think the desired Result that you want can be given by using GroupJoin()
The code Below will produce a structure like so
Field1, Field2, List < SubObject > null if empty
Sample code
var query = dc.Table1.Where(x => Table1_id == id).OrderBy(x => x.sort)
.GroupJoin(dc.Table2, (table1 => table1.Table1_id), (table2 => table2.Table2_id),
(table1, table2) => new MyObject
{
field1 = table1.Field1,
field2 = table1.Field2,
manySubObjects = (table2.Count() > 0)
? (from t in table2 select new SubObject { fielda = t.fielda, fieldb = t.fieldb}).ToList()
: null
}).ToList();
Dotnetfiddle link
UPDATE
From your comment I saw this
ga.Select(g = > new SubObject(){fielda = g.fielda, fieldb = g.fieldb})
I think it should be (depends on how "ga" is built)
ga.Select(g => new SubObject {fielda = g.fielda, fieldb = g.fieldb})
Please update your question with the whole query, it will help solve the issue.
** UPDATE BIS **
sentEmails = //ga.Count() < 1 ? null :
//(from g in ga select g).FirstOrDefault() == null ? null :
(from g in ga select new Email{
email_to = g.email_to,
email_from = g.email_from,
email_cc = g.email_cc,
email_bcc = g.email_bcc,
email_subject = g.email_subject,
email_body = g.email_body }).ToList()
Should be:
sentEmails = //ga.Count() < 1 ? null :
((from g in ga select g).FirstOrDefault() == null) ? null :
(from g in ga select new Email{
email_to = g.email_to,
email_from = g.email_from,
email_cc = g.email_cc,
email_bcc = g.email_bcc,
email_subject = g.email_subject,
email_body = g.email_body }).ToList()
Checks if the group has a First, if it doesn't the group doesn't have any records so the Action.Name for a Time Stamp has no emails to send. If the First isn't null the loop throw the group elements and create a list of Email,
var results =
(
// Use from, from like so for the left join:
from a in dc.Table1
from e in dc.Table2
// Join condition goes here
.Where(a.Id == e.Id)
// This is for the left join
.DefaultIfEmpty()
// Non-join conditions here
where a.Id == id
// Then group
group by new
{
a.Field1,
a.Field2
}
).Select(g =>
// Sort items within groups
g.OrderBy(item => item.sortField)
// Project required data only from each item
.Select(item => new
{
item.FieldA,
item.FieldB
}))
// Bring into memory
.ToList();
Then project in-memory to your non-EF-model type.

LINQ query not showing in DGV

I have been researching this for some time, so if I missed a topic somewhere please point me in the right direction and accept my apologies.
I am performing a LINQ query on an incoming DataTable and setting up new columns based on the filtering done. The information being passed in is a single row containing the columns: CompanyName, CustomerID, LastName, FirstName, ContactTitle.
My question is, am I over-filtering the information to the point where it will return nothing to the DGV, or have I done something else wrong?
What I am trying to do is query another table based on the information passed in from the DataTable. Here is my query:
var query = (from id in IncomingOrderDetails.AsEnumerable()
from o in db.Orders
from c in db.Customers
from r in db.Regions
where (id.Field<int>("OrderID") == o.OrderID)
where (o.CustomerID == c.CustomerID)
where (c.Region == r.RegionDescription)
select new
{
CustomerID = c.CustomerID,
CompanyName = c.CompanyName,
ContactName = c.ContactName,
RegionDescription = r.RegionDescription,
Country = c.Country,
Phone = c.Phone
}).ToList();
custInfoDGV.DataSource = query;
This line:
where (c.Region == r.RegionDescription)
...looks dubious. If c.Region = r.RegionDescription, why do you need to bring in r at all? All you use it for is retrieving the RegionDescription.
I don't know your tables, but joining two fields that don't match would certainly produce 0 records returned. :)

Comparing two datatables through Linq

Hi I'm trying to compare two datatable through Linq. But I get this exception:
Specific cast is invalid
Please help me as I am new to Linq. This is the code I'm using:
var matched1 = from table1 in dtAvailableStores.AsEnumerable()
join table2 in dtControlStores.AsEnumerable()
on table1.Field<int>("STORE_NBR")
equals table2.Field<int>("STORE_NBR")
select table1;
Here STORE_NBR is a string value.
You can have a fairly good idea with this piece of code:
var qry1 = datatable1.AsEnumerable().Select(a => new { MobileNo = a["ID"].ToString() });
var qry2 = datatable2.AsEnumerable().Select(b => new { MobileNo = b["ID"].ToString() });
var exceptAB = qry1.Except(qry2);
DataTable dtMisMatch = (from a in datatable1.AsEnumerable() join ab in exceptAB on a["ID"].ToString() equals ab.MobileNo select a).CopyToDataTable();
References:
Compare two datatable using LINQ Query
Compare two DataTables for differences in C#?
This would happen if that field isn't actually an int.

Linq : select value in a datatable column

How do you use LINQ (C#) to select the value in a particular column for a particular row in a datatable. The equivalent SQL would be:
select NAME from TABLE where ID = 0
Thanks for your answers. I didn't understand what type of object "MyTable" was (in your answers) and the following code gave me the error shown below.
DataTable dt = ds.Tables[0];
var name = from r in dt
where r.ID == 0
select r.Name;
Could not find an implementation of the query pattern for source type
'System.Data.DataTable'. 'Where' not found
So I continued my googling and found something that does work:
var rowColl = ds.Tables[0].AsEnumerable();
string name = (from r in rowColl
where r.Field<int>("ID") == 0
select r.Field<string>("NAME")).First<string>();
What do you think?
var name = from r in MyTable
where r.ID == 0
select r.Name;
If the row is unique then you could even just do:
var row = DataContext.MyTable.SingleOrDefault(r => r.ID == 0);
var name = row != null ? row.Name : String.Empty;
I notice others have given the non-lambda syntax so just to have this complete I'll put in the lambda syntax equivalent:
Non-lambda (as per James's post):
var name = from i in DataContext.MyTable
where i.ID == 0
select i.Name
Equivalent lambda syntax:
var name = DataContext.MyTable.Where(i => i.ID == 0)
.Select(i => new { Name = i.Name });
There's not really much practical difference, just personal opinion on which you prefer.
If the return value is string and you need to search by Id you can use:
string name = datatable.AsEnumerable().Where(row => Convert.ToInt32(row["Id"]) == Id).Select(row => row.Field<string>("name")).ToString();
or using generic variable:
var name = datatable.AsEnumerable().Where(row => Convert.ToInt32(row["Id"]) == Id).Select(row => row.Field<string>("name"));
var name = from DataRow dr in tblClassCode.Rows where (long)dr["ID"] == Convert.ToInt32(i) select (int)dr["Name"]).FirstOrDefault().ToString()
var x = from row in table
where row.ID == 0
select row
Supposing you have a DataTable that knows about the rows, other wise you'll need to use the row index:
where row[rowNumber] == 0
In this instance you'd also want to use the select to place the row data into an anonymous class or a preprepared class (if you want to pass it to another method)
Use linq and set the data table as Enumerable and select the fields from the data table field that matches what you are looking for.
Example
I want to get the currency Id and currency Name from the currency table where currency is local currency, and assign the currency id and name to a text boxes on the form:
DataTable dt = curData.loadCurrency();
var curId = from c in dt.AsEnumerable()
where c.Field<bool>("LocalCurrency") == true
select c.Field<int>("CURID");
foreach (int cid in curId)
{
txtCURID.Text = cid.ToString();
}
var curName = from c in dt.AsEnumerable()
where c.Field<bool>("LocalCurrency") == true
select c.Field<string>("CurName");
foreach (string cName in curName)
{
txtCurrency.Text = cName.ToString();
}

Categories