how to call sql string from nhibernate - nhibernate

i have the following method, at the moment it's return the whole sql string. How would i execute the following.
using (ITransaction transaction = session.BeginTransaction())
{
string sql =
string.Format(
#"DECLARE #Cost money
SET #Cost = -1
select #Cost = MAX(Cost) from item_costings
where Item_ID = {0}
and {1} >= Qty1 and {1} <= Qty2
RETURN (#Cost)",
itemId, quantity);
string mystring = session
.CreateSQLQuery(sql)
.ToString();
transaction.Commit();
return mystring;
}
// EDIT
here is the final version using criteria
using (ISession session = NHibernateHelper.OpenSession())
{
decimal cost = session
.CreateCriteria(typeof (ItemCosting))
.SetProjection(Projections.Max("Cost"))
.Add(Restrictions.Eq("ItemId", itemId))
.Add(Restrictions.Le("Qty1", quantity))
.Add(Restrictions.Ge("Qty2", quantity))
.UniqueResult<decimal>();
return cost;
}

NHibernate only supports reading results from data readers.
You should create your query string as:
string sql = string.Format(
#"select MAX(Cost) from item_costings
where Item_ID = {0}
and {1} >= Qty1 and {1} <= Qty2",
itemId, quantity);
And then you execute it with:
string mystring = session
.CreateSQLQuery(sql)
.UniqueResult<decimal>()
.ToString();
Anyway, you are not using NHibernate functionality here at all, you're just unnecessarily wrapping raw ADO.NET.
Why not define an object model and query it using Criteria, HQL or Linq?

Related

How to get year from string date c#

I have string date in sql server, and I want to retrieve all the rows greater than or equal the year of 2018 using ADO.Net. This is what I've accomplished but the result.HasRows() returns false although I already have rows in that table.
Is it something related to Culture?
UPDATE:
the problem was in data itself. there were some date in different format. it works now.
using (var command = connection.CreateCommand())
{
command.CommandText = $"SELECT *
$"FROM [dbo].[tableName] " +
$"WHERE Year(CAST([tableNmae].Date as datetime)) >= {2018} ";
using (var result = command.ExecuteReader())
{
if (result.HasRows)
{
while (result.Read())
{}
}
}
}
You cannot use CAST for the string type. You should use CONVERT instead of CAST
Why 104? Because I took this website as a reference.
http://www.sqlusa.com/bestpractices/datetimeconversion/
using (var command = connection.CreateCommand())
{
command.CommandText = $"SELECT *
$"FROM [dbo].[tableName] " +
$"WHERE Year(CONVERT(DATETIME,[tableNmae].Date,104)) >= {2018} ";
using (var result = command.ExecuteReader())
{
if (result.HasRows)
{
while (result.Read())
{}
}
}
}
NOTE: To use CONVERT, the column must not be of ntext type.
If you use it you will get this error.
Explicit conversion from data type ntext to datetime is not allowed.
Sample error if you don't use the correct dial type

How to insert multiple integer parameters into query?

Website user can enter search criteria to query orders. User, States, Status, OrderID, etc.
Website communicates with API. Query parameters are in the header, so I assume they come in as strings. API communicates with Access via Dapper.
For some criteria, they can send multiple values. So I want to use an "IN" clause.
where UserID in (150, 3303, 16547)
Dapper handles this nicely.
connection.Query<int>("select * from table where Id in #Ids", new { Ids = new int[] { 1, 2, 3 } });
This works in MS-Access
SELECT top 100 * from Orders where UserID in (150, 30330)
But that only works when the values are ints. String and Strings both give "Data type mismatch in criteria expression" in Access.
SELECT top 100 * from Orders where UserID in ("150", "30330") // two strings
SELECT top 100 * from Orders where UserID in ("150, 30330") // single string
It may be a coincidence, but all the examples I see are integers. Access throws an error on strings if you don't specify the size. Using DynamicParameters makes it easy to specify the size.
But when the field is an int, my dapper code gives the same error (Data type mismatch in criteria expression):
var paramlist = new DynamicParameters();
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
paramlist.Add("userId", userId, DbType.String, ParameterDirection.Input, 50);
sbWhere.AppendFormat("AND CustFID in (?) ", paramIndex++);
}
So I assume the issue is that I'm telling it that the parameter is a string.
But if I make the parameter an int, then it won't take the string with multiple values. Conversely, if I include the () in the string, it complains about the parens being missing from the 'in' clause.
I tried splitting the string of numbers into an array and/or list.
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
var userIds = userId.Split(','); //.ToList(); fails, can't map to native type
paramlist.Add("userId", userIds, DbType.String, ParameterDirection.Input, 1000);
if (userIds.Length > 1) {
sbWhere.AppendFormat("AND CustFID in #userId ", paramIndex++);
} else {
sbWhere.AppendFormat("AND CustFID = #userId ", paramIndex++);
}
}
and it gives ": No mapping exists from object type System.String[] to a known managed provider native type." whether I say the parameters are int32 or string.
UPDATE:
There may be multiple search criteria, so I'm using DynamicParameters.
Here is my attempt at implementing Palle Due's idea.
if ((!string.IsNullOrWhiteSpace(userId)) && userId != "0") {
// var userIds = userId.Split(',').Select(i => Int32.Parse(i)).ToList();// fails, can't map to native type
IEnumerable<int> userIds = userId.Split(',').Select<string, int>(int.Parse);
paramlist.Add("userId", userIds, DbType.Int32, ParameterDirection.Input);
if (userIds.Count() > 1) {
sbWhere.AppendFormat("AND CustFID in #userId ", paramIndex++);
} else {
sbWhere.AppendFormat("AND CustFID = #userId ", paramIndex++);
}
}
using (IDbConnection conn = Connection) {
string sQuery = string.Format("SELECT {0} FROM vwweb_Orders {1}", columns, where);
conn.Open();
var result = await conn.QueryAsync<Order>(sQuery, paramlist);
return result.ToList();
}
throws
Message: System.AggregateException : One or more errors occurred. (Failed to convert parameter value from a SelectArrayIterator`2 to a Int32.)
----> System.InvalidCastException : Failed to convert parameter value from a SelectArrayIterator`2 to a Int32.
----> System.InvalidCastException : Object must implement IConvertible.
The github page #Dai links to specifies that the Dapper list support only works with IEnumerable<int>.
But as I understand it your UserID is an int, so I don't get why you try to enter a string. You need to get the string the user has input and convert it to IEnumerable<int>. Do something like this:
IEnumerable<int> userIDs = (userId?? "").Split(',').Select<string, int>(int.Parse);
var result = connection.Query<int>("SELECT TOP 100 * FROM Orders WHERE UserID IN #Ids", new { Ids = userIDs });
You might want to apply some input checking to that, and you might also want to reconsider using Access as the "database" for a website. It's not what it was meant for.
I give up. Dapper should be able to handle this, but it's a newer feature, so...
I just built the IN clause myself.
if (userIds.Count() > 1) {
sbWhere.AppendFormat("AND CustFID in ( ");
int paramCnt = 0;
foreach (int id in userIds) {
sbWhere.AppendFormat("?, "); // Access doesn't mind a trailing ,
paramlist.Add("userId" + paramCnt.ToString(), id, DbType.Int32, ParameterDirection.Input);
paramCnt++;
}
sbWhere.AppendFormat(") ");
} else {
sbWhere.AppendFormat("AND CustFID = ? ");
paramlist.Add("userId", userIds.ToArray<int>()[0], DbType.Int32, ParameterDirection.Input);
}

How to convert values of a datatable from string to integer

I'm making a fine calculator in a library system. In it,I need to calculate the fine of a given day. For this,I use a data table to load the fine amounts and then,I need to calculate the total fine amount by adding each fine amount.But I'm having a problem in parsing the fine values which are in string format to integer.Here is a screenshot of the error.
Here is a screenshot of the error.
And here is the code which I used to convert the string values to integer and calculate the total fine.
int sum1 = 0;
int myNum;
String Display;
private void btnNext_Click(object sender, EventArgs e)
{
try
{
if (rbtnToday.Checked == true)
{
DateTime today = DateTime.Today;
Con.Open();
String select_today_query = "SELECT Fine FROM BookReceiveMem WHERE RecDate='" + today + "'";
Sqlda = new SqlDataAdapter(select_today_query, Con);
DataTable Dt = new DataTable();
Sqlda.Fill(Dt);
Con.Close();
foreach (DataRow row in Dt.Rows)
{
myNum = int.Parse(Dt.Columns[0].ToString());
sum1 = sum1 + myNum;
}
Display = sum1.ToString();
MessageBox.Show("Today Fine Amount is= " + Display, "Today Fine Calculation", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
Is there any method to solve this problem?
Databases are really good at calculating things like a sum. If Fine is an integer in your database you can get it to sum all the rows and just return that:
SELECT SUM(Fine) As TotalFine
FROM BookReceiveMem
WHERE RecDate = #recDate
Which you could call from code without ever needing a DataTable as follows:
using(var cmd = Con.CreatCommand())
{
cmd.CommandText = "SELECT SUM(Fine) As TotalFine FROM BookReceiveMem WHERE RecDate = #recDate";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#recDate",DateTime.Today);
var result = (int)cmd.ExecuteScalar();
MessageBox.Show("Today Fine Amount is= " + result, "Today Fine Calculation", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Note that the above uses a Parameterized Query which is much safer than using string concatenation
However, a more direct answer to your question:
myNum = int.Parse(Dt.Columns[0].ToString());
Here you're getting the Column and trying to turn that to an integer. What you actually meant to do was get the row value (and you dont need to Parse it - it's already an integer!)
myNum = (int)row["Fine"];

Hibernate query to get Total number of entries in a column with a specific value

I am pretty new to hibernate. So this could be a simple question for you all.
I have a Table called BuildHistory. In that i have a column with name Status.
I want to get total count of entries in that table whose status value is SUCCESS.
UPDATE
This is my method which i use for getting the count.
public Object countStatus(String sql){
Session session = HibernateServeletContextListner.sessionFactory_Dummy.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Query query = session.createQuery("select sum(case when bh.status = :"+sql+" then 1 else 0 end) from BuildHistory bh");
tx.commit();
// return query.uniqueResult();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return 0;
}
You should be able to use conditional aggregation with HQL. Something like the following should work:
select sum(case when bh.status = :success then 1 else 0 end)
from BuildHistory bh
You might use the following Java code:
String hql = "select sum(case when bh.status = :status then 1 else 0 end) ";
hql += "from BuildHistory bh";
Query query = session.createQuery(hql);
query.setParameter("status", "success");
int sum = (Integer)query.uniqueResult();
One important point here is that we are binding the :status parameter here dynamically using a prepared statement. In your original code, you were attempting to concatenate the query together, which is prone to error, and SQL injection.

Insert SQL statement is not working after checking against quantities from tables in database

I created a sale table which Insert function does not work properly. It shows the error message
Must declare the scalar variable "#iProductID"
at the statement
using (var sdRead = cmdOrder.ExecuteReader())
I am really stuck here. I also want to know how I can achieve for inserting SaleID with auto-increment without with any input field at the form. Every time I insert a new record, SaleID should be auto-generated and saved in the database.
My code below work like this. I checked available stocks from my Product table. If quantity order is greater than quantity from Product table, show error message.
Otherwise, proceed to inserting order information into Sale table. Any help is appreciated.
private void btnOrder_Click(object sender, EventArgs e)
{
int iQuantityDB;
int iCustomerID = Convert.ToInt32(txtCustomerID.Text);
int iProductID = Convert.ToInt32(txtProductID.Text);
decimal dPrice = Convert.ToDecimal(txtPrice.Text);
int iQuantity = Convert.ToInt32(txtQuantity.Text);
decimal dSubtotal = Convert.ToDecimal(txtSubTotal.Text);
decimal dGST = Convert.ToDecimal(txtGST.Text);
decimal dTotal = Convert.ToDecimal(txtTotal.Text);
string strConnectionString = #"Data Source = KK\SQLEXPRESS; Integrated Security = SSPI; Initial Catalog = JeanDB; MultipleActiveResultSets=True;";
using (var sqlconn = new SqlConnection(strConnectionString))
{
sqlconn.Open();
string querySelectQuantity = #"Select Quantity from dbo.JeanProduct WHERE ProductID = #iProductID";
using (var cmdOrder = new SqlCommand(querySelectQuantity, sqlconn))
{
using (var sdRead = cmdOrder.ExecuteReader())
{
sdRead.Read();
iQuantityDB = Convert.ToInt32(sdRead["Quantity"]);
}
}
if (iQuantityDB > iQuantity)
{
string InsertQuery = #"INSERT INTO Sale(CustomerID, ProductID, Price, Quantity, Subtotal, GST, Total)VALUES(#iCustomerID, #iProductID, #dPrice, #iQuantity, #dSubtotal, #dGST, #Total)";
using (var InsertCMD = new SqlCommand(InsertQuery, sqlconn))
{
InsertCMD.Connection = sqlconn;
InsertCMD.Parameters.AddWithValue("#iCustomerID", iCustomerID);
InsertCMD.Parameters.AddWithValue("#iProdcutID", iProductID);
InsertCMD.Parameters.AddWithValue("#dPrice", dPrice);
InsertCMD.Parameters.AddWithValue("#iQuantity", iQuantity);
InsertCMD.Parameters.AddWithValue("#dSubtotal", dSubtotal);
InsertCMD.Parameters.AddWithValue("#dGST", dGST);
InsertCMD.Parameters.AddWithValue("#dTotal", dTotal);
InsertCMD.ExecuteNonQuery();
LoadDataonTable();
}
}
else
{
MessageBox.Show("no more stock");
}
sqlconn.Close();
}
}
At the line using (var sdRead = cmdOrder.ExecuteReader()) your SQL SELECT query is using a parameter - WHERE ProductID = #iProductID - but this hasn't been set. Hence the error message Must declare the scalar variable "#iProductID"
Just add cmdOrder.Parameters.AddWithValue("#iProductID", iProductID) between defining the SQL and executing it, and that should clear that problem.
Moving on to the next one - you're using AddWithValue("#dTotal" but it's #Total in the SQL :)