How to do a Join if it passes a condition? - c#

I would like to do an if statement within my query, but I'm not sure how. I want to perform:
join asoc2 in Personnels
on comp.Secondary_associate equals asoc2.Dpinitials
if there is a Second_Person data available. Any ideas how to do this? Let me know if there's an easier way. Here's my complete query:
(from sc in Data
join comp in Companies
on sc.Company equals comp.Company
join anl in Personnels
on sc.SalesP_initials equals anl.Dpinitials
join asoc1 in Personnels
on comp.First_associate equals asoc1.Dpinitials
join asoc2 in Personnels
on comp.Second_Person equals asoc2.Dpinitials
select new {
MyCompany = sc.Company,
ReleaseDate = sc.Release_date,
WebHeadline = sc.Short_subject,
EmailTo =
anl.Last_name + ", " + anl.First_name + " <" + anl.Email_address.Trim() + ">; "
+
asoc1.Last_name + ", " + asoc1.First_name + " <" + asoc1.Email_address.Trim() + ">; "
+
asoc2.Last_name + ", " + asoc2.First_name + " <" + asoc2.Email_address.Trim() + ">"
}).FirstOrDefault ()
Right now, it just displays null because *comp.Second_Person* doesn't exist.

You can use "where" in linq to filter your data

Related

Error occuring in Select Into Statement

I have the following statement which has a syntax error in the 'From' clause, which has a couple of curly table names. The actual database names are the same as the tables, so they are all seperate.
I open a connection to the SealRegister mdb, which is empty (no tables yet), then ExecuteNonQuery on the statement. This I think should create the table SealRegister in the SealRegister.mdb.
sqlcommand = #"Select ""Plant"" As Geometry, A.Asset_ID, B.RoadID, A.AssetType, B.RoadName, B.SegmentNo, C.AadtCount, C.CommVehCnt " +
#"Into [SealRegister] " +
#"From [C:\AR\Plant\Accounting\2015].ARPlntPA_2015_07-2016_06+10yrs As A " +
#"LEFT OUTER JOIN ([C:\AR\Lines\Accounting\2015].ARLnPA_2015_07-2016_06+10yrs As B " +
#"LEFT OUTER JOIN [C:\AR\Lines\TEMP].ARLnX As C On B.Asset_ID = C.Asset_ID) On A.Parent_ID = B.Asset_ID " +
#"WHERE AssetType = 'Wearing Course'";
What do I need to do to correct the syntax
[EDIT]
connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data
Source=C:\AR\TEMP\SealRegister.mdb"
This works:
sqlcommand = #"Select ""Plant"" As Geometry, A.Asset_ID, B.RoadID, A.AssetType, B.RoadName, B.SegmentNo, C.AadtCount, C.CommVehCnt " +
#"Into [SealRegister] " +
#"From [C:\AR\Plant\Accounting\2015\ARPlntPA_2015_07-2016_06+10yrs].[ARPlntPA_2015_07-2016_06+10yrs] As A " +
#"LEFT OUTER JOIN ([C:\AR\Lines\Accounting\2015\ARLnPA_2015_07-2016_06+10yrs].[ARLnPA_2015_07-2016_06+10yrs] As B " +
#"LEFT OUTER JOIN [C:\AR\Lines\TEMP].ARLnX As C On B.Asset_ID = C.Asset_ID) On A.Parent_ID = B.Asset_ID " +
#"WHERE AssetType = 'Wearing Course'";

SQL Server 2012 : Between issue with parameters

I am having an issue with the query below:
SELECT
tT.RequestID,
TStatus,
TLead,
RequestDate,
tG.Category,
tETM.RAgency,
ECost,
tTT.TType
FROM
tT AS tT
INNER JOIN
tTMain AS tETM ON tT.RequestID = tETM.RequestID
INNER JOIN
tTType AS tTT ON tETM.AMod = tTT.TypeID
INNER JOIN
tGup AS tG ON tT.Category = tG.CategoryID
WHERE
tT.active = 1
AND (ApproxDate BETWEEN '09/30/2016' AND '09/30/2017')
AND tT.Category = 3
I am currently getting an error:
Conversion failed when converting date and/or time from character string.
The way I populate the above query in code:
string theQ = "SELECT " +
"tT.RequestID, " +
"TStatus, " +
"TLead, " +
"RequestDate, " +
"tG.Category, " +
"tETM.RAgency, " +
"ECost, " +
"tTT.TType " +
"FROM " +
"tT AS tT " +
"INNER JOIN " +
"tTMain AS tETM " +
"ON " +
"tT.RequestID = tETM.RequestID " +
"INNER JOIN " +
"tTType AS tTT " +
"ON " +
"tETM.AMod = tTT.TypeID " +
"INNER JOIN " +
"tGup AS tG " +
"ON " +
"tT.Category = tG.CategoryID " +
"WHERE " +
"tT.active = #val1 " +
"AND " +
"(ApproxDate BETWEEN #val2 AND #val3) " +
"AND " +
"tT.Category = #val4"
//Split up the between check. (it looks like this: BETWEEN 'xx/xx/xxxx' AND 'xx/xx/xxxx')
string[] betweenSplit = Regex.Split(Session["between"].ToString(), " AND ");
SqlDataAdapter da = new SqlDataAdapter();
DataSet _ds1 = new DataSet();
command = new SqlCommand(theQ, con);
command.Parameters.AddWithValue(1, "1");
command.Parameters.AddWithValue(2, betweenSplit[0].Replace(" BETWEEN ", ""));
command.Parameters.AddWithValue(3, betweenSplit[1]);
command.Parameters.AddWithValue(4, Session["UCat"].ToString());
da = new SqlDataAdapter(command);
da.Fill(_ds1, dbName);
da.Dispose();
closeAllConnections();
command.Parameters.Clear();
The error occurs on the line:
da.Fill(_ds1, "tripData");
What would I be doing incorrectly because the same query above works just fine when running it in Server Management Studio?
I suggest to avoid implicit conversion of date to/from string.
In your case it could be (for example):
CONVERT (datetime, '09/30/2016',101)
You should pass Datetime parameter to SQL like that
var yourFromDate = DateTime.Now;
SqlParameter fromDate = new SqlParameter("#val2", SqlDbType.DateTime) {Value = yourFromDate};
command.Parameters.Add(fromDate);

Choosing a column for multiple row queries

At the moment I am trying to query a broken database in c#. The recently introduced error is that when data is input in a particular way, a value in a column is defaulted to 0, which is problematic for me, as I have no control over what the user does or what the dba does.
To get around this, I have found another path to the data I need to output to the user. Problem is there is I have the requirement from my supervisor to support the old method in the event of the column coming up as a non-zero number.
I am trying to do this with either a case or an if command, but I not that great with sql, so I am not 100% sure where I am going wrong or how to go about it properly/efficiently. These are the commands in their current states:
SqlCommand caseCmd = new SqlCommand(
"SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, TC.DOCLE, TC.ICPC, TC.ICD10, TERMCODE =" +
" CASE H.ITEMCODE WHEN 0" +
" THEN TN.TERMID" +
" ELSE H.ITEMCODE END" +
" FROM " + _databaseName + ".dbo.PASTHISTORY H" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMNAMES TN ON TN.TERMNAME = H.ITEMTEXT" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = TERMCODE" +
" INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = TERMCODE" +
" WHERE H.INTERNALID = #patientid" +
" AND H.RECORDSTATUS = 1" +
" AND ((H.CREATED >= #mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate)))" +
" AND TC.RECORDSTATUS = 1",
Connection);
caseCmd.Parameters.AddWithValue("#patientid", int.Parse(patientId));
caseCmd.Parameters.AddWithValue("#mindate", minEnteredDate);
// Current error:
// When using 'TC.TERMID = TERMCODE', I get the error 'The conversion of the varchar value
// "3951000119103 " overflowed an int column'.
// This is alleviated by using either TN.TERMID OR H.ITEMCODE
SqlCommand ifCmd = new SqlCommand(
"IF (H.ITEMCODE = 0)" +
" SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, TC.DOCLE, TC.ICPC, TC.ICD10, TN.TERMID" +
" FROM " + _databaseName + ".dbo.PASTHISTORY H" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMNAMES TN ON TN.TERMNAME = H.ITEMTEXT" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = TN.TERMID" +
" INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = TN.TERMID" +
" WHERE H.INTERNALID = #patientid" +
" AND H.RECORDSTATUS = 1" +
" AND ((H.CREATED >= #mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate)))" +
" AND TC.RECORDSTATUS = 1" +
" ELSE IF (H.ITEMCODE <> 0)" +
" SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, H.ITEMCODE, TC.DOCLE, TC.ICPC, TC.ICD10" +
" FROM " + _databaseName + ".dbo.PASTHISTORY H" +
" INNER JOIN " + _drugDatabaseName + ".dbo.TERMCODES TC ON TC.TERMID = H.ITEMCODE" +
" INNER JOIN " + _drugDatabaseName + ".dbo.CONDITIONS C ON C.TERMID = H.ITEMCODE" +
" WHERE H.INTERNALID = #patientid" +
" AND H.RECORDSTATUS = 1" +
" AND ((H.CREATED >= #mindate) OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate)))" +
" AND TC.RECORDSTATUS = 1",
Connection);
ifCmd.Parameters.AddWithValue("#patientid", int.Parse(patientId));
ifCmd.Parameters.AddWithValue("#mindate", minEnteredDate);
// Current error:
// Getting two lines both saying 'The multi-part identifier "H.ITEMCODE" could not be bound.'
// I trust this is because of the IF and ELSE IF statements.
// Starting to think IF isn't the answer for me.
// Use either
SqlDataReader rdr = caseCmd.ExecuteReader();
// or
// SqlDataReader rdr = ifCmd.ExecuteReader();
Is this even remotely feasible or should I look into just making two sql commands for both alternatives and search through them both?
For clarity I took SQL out of C# string and used CTE. Basically, you can first patch the data and then use it for the lookups:
WITH PatchedHistory AS (
SELECT
H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT
, COALESCE(TN.TERMID, H.ITEMCODE) AS ITEMCODE --< TERMID with ITEMCODE fall-back
FROM _databaseName.dbo.PASTHISTORY H
LEFT JOIN _drugDatabaseName.dbo.TERMNAMES TN
ON H.ITEMCODE = 0 --< Lookup only if ITEMCODE is 0
AND TN.TERMNAME = H.ITEMTEXT
WHERE H.INTERNALID = #patientid --< Apply most of the filtering here
AND H.RECORDSTATUS = 1
AND ((H.CREATED >= #mindate) --< Suspicious condition
OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate))
)
)
SELECT H.CREATED, H.STATUSCODE, H.DETAILS, H.YEAR, H.MONTH, H.DAY, H.ITEMTEXT, H.ITEMCODE
, TC.DOCLE, TC.ICPC, TC.ICD10 --< Add the rest of the data
FROM PatchedHistory H
INNER JOIN _drugDatabaseName.dbo.TERMCODES TC
ON TC.TERMID = H.ITEMCODE --< Join on the "patched" ITEMCODE
INNER JOIN _drugDatabaseName.dbo.CONDITIONS C
ON C.TERMID = H.ITEMCODE --< Join on the "patched" ITEMCODE
WHERE TC.RECORDSTATUS = 1
Also this condition looks suspicious:
AND ((H.CREATED >= #mindate)
OR ((H.UPDATED IS NOT NULL) AND (H.UPDATED >= #mindate))
)
technically it is equivalent to just
AND ((H.CREATED >= #mindate) OR (H.UPDATED >= #mindate))
It looks like the intention was
AND COALESCE(H.UPDATED, H.CREATED) >= #mindate

No value given for one or more required parameters c#

An error appear when i want to execute my SQL statement in C# application, which it's:
No value given for one or more required parameters.
I'm using c# with MS access database.
This is my code:
string string2 = "";
if (radButton2 != null)
{
string2 = " and signaal1.info='" + radButton2.Text + "' ";
}
else
string2 = " and signaal1.info='0' ";
if (radButton3 != null)
{
string2 += " and situation.info='" + radButton3.Text + "' ";
}
OleDbCommand cmd = new OleDbCommand("SELECT actionz.info, relationz.id AS actionz FROM ((((relationz LEFT OUTER JOIN conditions ON relationz.conditions_id = conditions.id) LEFT OUTER JOIN situation ON relationz.situation_id = situation.id) LEFT OUTER JOIN car_type ON relationz.car_id = car_type.id) LEFT OUTER JOIN actionz ON relationz.action_id = actionz.id) LEFT OUTER JOIN signal AS signaal1 ON relationz.signal_id = signaal1.id where car_type.info='" + radButton1.Text + "' " + string2 + " ORDER BY conditions.id ASC", objConn);
//cmd.Parameters.AddWithValue("#car_type", radButton1.Text);
OleDbDataReader dataReader = cmd.ExecuteReader();
Typo:
" ...info='" + radButton1.Text + "' " + string2 + " ORDER BY ..."
should be
" ...info='" + radButton1.Text + string2 + "' ORDER BY ..."
or if you need the space between the values:
" ...info='" + radButton1.Text + " " + string2 + "' ORDER BY ..."
Open to Injection though as mentioned.

Rewriting postgres query to NHibernate

Please can you advise how I can write the following using NHibernate's QueryOver<>() Query<>() or other NHibernate method that will not involve me rewriting this (and numerous other similar queries) when switching DB provider?
The subqueries with multiple table joins are making this a pain for me to translate with my limited exposure of NHibernate.
return Session.CreateSQLQuery("select " +
" boards.id, boards.name, boards.description, " +
" (" +
" select " +
" count(topic.id) " +
" from topic " +
" left join users on users.id=topic.user " +
" left join boards b on b.id=topic.bid " +
" left join boards b2 on b2.id=b.bid " +
" where (topic.bid=boards.id or b.bid = boards.id or b2.bid = boards.id) " +
" and (b.type <= (:userType)) " +
" and (b2.type is null or b2.type <= (:userType)) " +
" and users.type > 0 " +
" and users.chatban = 0" +
" ) as TopicCount," +
" (" +
" select (max(posts.time) - max(read.time)) as t " +
" from posts " +
" left join users u on u.id=posts.user" +
" left join topic on topic.id=posts.tid " +
" left join read on read.topic=topic.id and read.userid=(:userId) " +
" left join boards b on b.id=topic.bid" +
" left join boards b2 on b2.id=b.bid" +
" where " +
" (topic.bid=boards.id or b.bid = boards.id or b2.bid = boards.id) " +
" and (b.type <= (:userType)) " +
" and (b2.type is null or b2.type <= (:userType)) " +
" and not exists (select boardid from boardhigh where boardid=b.id and userid=(:userId))" +
" and u.type > 0 " +
" and u.chatban = 0 " +
" group by topic.id " +
" order by t desc " +
" limit 1" +
" ) as time " +
"from boards " +
"left join topic on topic.bid=boards.id " +
"where" +
" boards.type <= (:userType) " +
(parentBoard.HasValue ? " and boards.bid = " + parentBoard.Value : "") +
"group by boards.id, boards.name, boards.description, boards.display " +
"order by boards.display desc, boards.name asc"
)
.SetInt32("userType", (int)UserHelper.LoggedInUser.UserType)
.SetInt64("userId", UserHelper.LoggedInUser.Id)
.List()
.Cast<object[]>()
.ToList()
.Select(x => new BoardValueObject
{
Id = (int)x[0],
Name = x[1].ToString(),
Description = x[2].ToString(),
TopicCount = (long)x[3],
Time = x[4] as int?
})
.ToList();
Thanks
I would heavily doubt that you'll ever recieve answer for your giant SQL Query - and its conversion. Meanwhile, I would like to point out some differences in approach/thinking when using NHibernate.
Use entities first. Define your model, the business domain model with Users, Topics, Boards.
Spend some time to understand the lazy loading. Lot of data could be recieved by simple query to get User(s), and then nagivating to his boards, topics... All data needed will be loaded in separted SQL statements, but without complex querying.
Do check the advantages fo batch-loading, which is a technique how to avoid 1+N SELECT issue. It is really working well and has surprisingly large effect on amount of issued SQL statements.
DO NOT WORRY to use native SQL to recieve "..." data required by users (replace dots with words like crazy, unbelievable, complex). NHibernate is ORM at first place. It does great job for all CRUD operations related to Business object model. Any "SP like selects" are supported but indirectly... via CreateSQLQuery
So, try to start with simple stuff and once that is working, even the complex one will.

Categories

Resources