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.
Related
I am getting the following error.
Message = "Incorrect syntax near the keyword 'AS'.\r\nIncorrect syntax near the keyword 'AS'."
I have the following sql string query.
private const string QueryString =
"SELECT DISTINCT "
+ " Person.[PersObjId]"
+ ",Person.[PtObjId]"
+ ",MSN.[PersObjId]"
+ ",MSN.[ExtrnId] AS '" + MSNumber + "'"
+ ",HlthProfMstrV.[RptName] AS '" + ItemName + "'"
+ ",HlthProfMstrV.[ItemStsId] AS '" + ItemId + "'"
+ "FROM [dbt1].[Person]"
+ "join"
+ " ( "
+ " SELECT "
+ " PersIdRptV.PersObjId"
+ " , PersIdRptV.ExtrnId"
+ " FROM"
+ " dbt1.PersIdRptV"
+ " join dbt1.IdIssMstrV on PersIdRptV.IdIssObjId = IdIssMstrV.IdIssObjId"
+ " WHERE"
+ " PersIdRptV.TypeId = 5"
+ " and"
+ " PersIdRptV.StpDate is NULL"
+ " ) AS MSN on dbt1.Person.PersObjId = MSN.PersObjId"
+ "left join dbt1.HlthProfMstrV on Person.PCPHlthProfObjId = HlthProfMstrV.HlthProfObjId"
+ " " + "WHERE" + " "
+ "Person.[ExpressId] =12"
+ " and" + " "
+ "Person.[StnTst] = 'Actv' "
+ " and" + " "
+ "MSN.[ExtrnId] = #MSN ";
I think this error is occuring when I am getting the first join result where I assign the result set to "MSN". I tried taking out the AS from AS MSN and I get another error saying the following:
Message = "Incorrect syntax near the keyword 'MSN'.\r\nIncorrect
syntax near the keyword 'MSN'."
I been looking at this for few hours. I am sure its something simple I am missing. Help appreciated!
You're missing a space between last column alias and From keyword:
+ ",HlthProfMstrV.[ItemStsId] AS '" + ItemId + "'"
+ " FROM [dbt1].[Person]"
Space missing before person and join
+ "FROM [dbt1].[Person]"
+ " join" --> Added space before join
+ "MSN.[ExtrnID] = '" + #MSN + "'"
This is my code
string stR = "INSERT INTO CHECKINOUT (USERID,CHECKTIME,CHECKTYPE,VERIFYCODE,SENSORID,WorkCode) " +
" SELECT a.USERID,c.CHECKTIME,c.CHECKTYPE,c.VERIFYCODE,c.SENSORID,c.WorkCode " +
" FROM USERINFO a " +
" JOIN [MS Access;DATABASE=" + open.FileName + "].USERINFO b " +
" ON a.BadgeNumber=b.Badgenumber " +
" JOIN [MS Access;DATABASE=" + open.FileName + "].CHECKINOUT c " +
" ON b.USERID=c.USERID " +
" WHERE NOT EXISTS " +
" (SELECT a.USERID,c.CHECKTIME,c.CHECKTYPE,c.VERIFYCODE,c.SENSORID,c.WorkCode " +
" FROM USERINFO a " +
" JOIN [MS Access;DATABASE=" + open.FileName + "].USERINFO b " +
" ON a.BadgeNumber=b.Badgenumber " +
" JOIN [MS Access;DATABASE=" + open.FileName + "].CHECKINOUT c " +
" ON b.USERID=c.USERID)";
I got exception error "Syntax error in FROM clause"
Note: I already exported all ms access tables to ms sql 2000 database and this script is working fine with no error, but with ms access I receive this kind of error, This is the first time I'm using ms access as back end, this is an old program in my office that I need to fix error.
My first question is which FROM clause is failing. I would test each portion separately. Does the query work if you remove the WHERE NOT EXISTS clause? If so then the problem is in the subquery WHERE NOT EXISTS is referencing.
I had a query answered here SQL Select All Without Values in Another Table.
I've just been asked to integrate the data from another database. This is what I have at the moment.
string _loanSubcontractor = TableNames.Default.LoansSubcontractors;
string _loanPacific = TableNames.Default.LoansPacific;
string _tools = TableNames.Default.Tools;
string _selectStatement = " SELECT [Tools].[Type], [Tools].[Brand], [Tools].[Serial], [Tools].[Year], [Tools].[Code] ";
string _groupBy = " GROUP BY [Tools].[Type], [Tools].[Brand], [Tools].[Serial], [Tools].[Year], [Tools].[Code], [Tools].[Working] ";
string _searchItems = " ([Tools].Code LIKE #toolSerial OR [Tools].Serial LIKE #toolSerial) AND ([Tools].[Working] = 'True' OR [Tools].[Working] IS NULL) ";
SqlConnection myConnection = new SqlConnection(Connection.Default.ConnectionString);
//Checks the main tool information
myConnection.Open();
SqlCommand getTool = new SqlCommand(
_selectStatement + "FROM [" + _tools + "] LEFT OUTER JOIN [" + _loanSubcontractor + "] ON " +
_tools + ".code = [" + _loanSubcontractor + "].ToolCode FULL JOIN [" + _loanPacific + "] ON " + _tools + ".Code = " +
_loanPacific + ".ToolCode WHERE [" + _loanSubcontractor + "].ToolCode IS NULL AND [" + _loanPacific + "].ToolCode IS NULL AND (" + _searchItems + ")" +
"UNION " +
_selectStatement + " FROM [" + _loanSubcontractor + "] INNER JOIN " + _tools + " ON " + _tools + ".Code = [" + _loanSubcontractor + "].ToolCode " +
"INNER JOIN " + _loanPacific + " ON " + _loanPacific + ".ToolCode = " + _tools + ".Code " + _groupBy +
"HAVING (COUNT(" + _loanSubcontractor + ".ReturnDate) = COUNT(*) OR COUNT(" + _loanPacific + ".ReturnDate) = COUNT(*)) " +
" AND " + _searchItems, myConnection);
getTool.Parameters.Add("#toolSerial", SqlDbType.NVarChar).Value = "%" + toolSerial + "%";
What I have is two loan tables (one for employees and one for subcontractors) because the attribute names are different and the data types are also different. Essentially, I need to check that the tool is working, and the tool is not hired out in either of the loan tables (as shown by the return date being null). There may or may not be a loan in either of the tables.
Also, could someone provide me with a link that shows good formatting techniques for SQL within C#?
i sagest you use linq to SQL . this is a part of ADO.NET and you can use long query with 100 % acres and easy way
msdn.microsoft.com for linq to SQL
LINQ to SQL: .NET Language-Integrated Query for Relational Data
Simple LINQ to SQL in C#
Firstly apologies for the woolly subject title, its hard to put this one into words.
So…with that in mind I’ve attached a database relationship diagram (see below) which will hopefully explain it much more concisely.
We have inherited a large database (and therefore have no ability to change/rationalise it, more’s the pity!) which has a troublesome ‘loop’ of 4 tables that have a couple of different many to many relationships within.
I need to be able to get out the Court’s name, full address, and general notes, all of which every court will only have one of, followed by the Contact details which are divided into two groups (general and specific contact points) which could contain one or more listings dependent on the court. I need this to appear in the format below:
Abergavenny Magistrates' Court
Abergavenny
NP7 5DL
This court is open for hearings only. Additional Court Notes….
Contacts
Switchboard: 01633 64xxxx
Fax: 01633 64xxxx
Service 1: 01633 64xxxx
Service 2: 01633 64xxxx
Contact Name 1 - Acting Court Manager: 01633 64xxxx
Contact Name 2 - Acting Office Manager: 01633 64xxxx
Contact Name 3 - Acting List Officer: 01633 64xxxx
Contact Name 4 - Justices' Clerk: 01633 64xxxx
I posted on StackOverflow yesterday to find out how to correctly write the SQL query and ASP.NET C# code for one many-to-many relationship. For simplicity’s sake the info I provided was very much paraphrased and basically contained only half of the loop you see above. However I’ve since failed in my attempt to apply the same principles to the full loop.
The SQL query (which works for the first half of the loop, i.e. to provide the court address details and a list of the specific contact points) looks like this:
string myQuery =
"SELECT C.court_id, court_name, court_addr1, court_town_name, court_county_name, " +
"court_country_name, court_addr_pcode, court_addr_dx, court_code, court_note, " +
"court_contacts_name, court_contacts_no, CCT.court_contact_type_desc " +
"FROM court C " +
"JOIN court_addr CA ON C.court_addr_id = CA.court_addr_id " +
"JOIN court_town CT ON CA.court_town_id = CT.court_town_id " +
"JOIN court_county CC ON CT.court_county_id = CC.court_county_id " +
"JOIN court_country CCO ON CC.court_country_id = CCO.court_country_id " +
"JOIN court_contacts CCON ON C.court_id = CCON.court_id " +
"JOIN court_contact_type CCT ON CCON.court_contact_type_id = CCT.court_contact_type_id " +
"WHERE C.court_id = '25' " +
"ORDER BY C.court_id";
Whilst the C# looks like this:
if (myDataReader.HasRows)
{
string last_id = string.Empty;
while (myDataReader.Read())
{
string court_id = myDataReader["court_id"].ToString();
string court_name = myDataReader["court_name"].ToString();
string court_addr = myDataReader["court_addr1"].ToString();
string court_town = myDataReader["court_town_name"].ToString();
string court_county = myDataReader["court_county_name"].ToString();
string court_country = myDataReader["court_country_name"].ToString();
string court_pcode = myDataReader["court_addr_pcode"].ToString();
string court_dx = myDataReader["court_addr_dx"].ToString();
string court_code = myDataReader["court_code"].ToString();
string court_note = myDataReader["court_note"].ToString();
string court_contact_name = myDataReader["court_contacts_name"].ToString();
string court_contact_desc = myDataReader["court_contact_type_desc"].ToString();
string court_contact_no = myDataReader["court_contacts_no"].ToString();
if (last_id != court_id) {
Response.Write("<strong>" + court_name + "</strong><br>" + court_addr +
"<br>" + court_town + "<br>" + court_county + "<br>" +
court_country + "<br>" + court_pcode + "<br><br>" +
court_dx + "<br><p>Court code " + court_code + "</p><p>" +
court_note + "</p>" + court_contact_name + " - " +
court_contact_desc + ": " + court_contact_no + "<br>");
} else {
Response.Write("<br>" + court_contact_name + " - " + court_contact_desc +
": " + court_contact_no + "<br>");
}
last_id = court_id;
}
}
Following the same logic in the SQL query I’ve tried to add an additional SELECT parameter of court_contacts_general_no and a couple of extra JOIN lines to bring in the court_contacts_general table (see below), however, this produces errors along the lines of ‘The correlation name CCG is specified multiple times in a FROM clause’ or just goes completely blank if the 2nd correlation name is removed.
"JOIN court_contacts_general CCG ON C.court_id = CCG.court_id " +
"JOIN court_contacts_general CCG ON CCT.court_contact_type_id = CCG.court_contact_type_id " +
Whilst in the C# I’ve added a new string for court_contact_general_no and tried creating another if/else loop based on writing the response received from this new variable.
Either way, all I’m getting is a big blank page or the SQL related errors above.
Any ideas?
Thanks in advance for all/any help.
You'll need to use different table name aliases in order to join the same table more than one time in a single query
JOIN court_contacts_general CCG1
JOIN court_contacts_general CCG2.. etc
I'd recommend naming the tables something more relevant to what data is being returned though in that case
It's certainly not elegant (no doubt there's a much better way of writing it!) but I've managed to work out a solution to the problem by writing a second SQL query and opening a second Sqlconnection directly after the first one has closed to tag on the second batch of contacts.
SQL query:
string myQuery2 =
"SELECT C.court_id, court_contacts_name, court_contacts_no, court_contact_type_desc " +
"FROM court C " +
"JOIN court_contacts CCON ON C.court_id = CCON.court_id " +
"JOIN court_contact_type CCT ON CCON.court_contact_type_id = CCT.court_contact_type_id " +
"WHERE C.court_id = '" + court_id_no + "' " +
"ORDER BY C.court_id";
C# code:
myDataReader.Close();
connection.Close();
SqlConnection connection2 = new SqlConnection(connStr);
SqlCommand myCommand2 = new SqlCommand(myQuery2, connection2);
SqlDataReader myDataReader2;
connection2.Open();
myDataReader2 = myCommand2.ExecuteReader();
if (myDataReader2.HasRows) {
string last_id = string.Empty;
while (myDataReader2.Read()) {
string court_id = myDataReader2["court_id"].ToString();
string court_contact_desc = myDataReader2["court_contact_type_desc"].ToString();
string court_contact_name = myDataReader2["court_contacts_name"].ToString();
string court_contact_no = myDataReader2["court_contacts_no"].ToString();
if (string.IsNullOrWhiteSpace(court_contact_no)) {
court_contact_no = generic_contact_no;
}
if (last_id != court_id) {
Response.Write(court_contact_name + " - " + court_contact_desc + ": " + court_contact_no + "<br>");
} else {
Response.Write(court_contact_name + " - " + court_contact_desc + ": " + court_contact_no + "<br>");
}
last_id = court_id;
}
}
As I say, not pretty but the important thing is it works.
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