How can I select the maximum value in NHibernate? - nhibernate

I need to get maximum page order from database:
int maxOrder = GetSession.Query<Page>().Max(x => x.PageOrder);
The above works if there are rows in the database table, but when table is empty I'm getting:
Value cannot be null.
Parameter name: item

In the way you are doing it is normal to get an exception as the enumerable, that the GetSession.Query<Page>() returns, is empty (because the table is empty as you mentioned).
The exception that you should be getting is: Sequence contains no elements.
The exception you mention in your question is because the item variable (which is irrelevant with the NHiberanate query you list above) is null (line 54 assigns the item property to null).
A safer way to get the max from a property in a table would be the following:
var max = GetSession.CreateCriteria<Page>()
.SetProjection(Projections.Max("PageOrder"))
.UniqueResult();
or using QueryOver with NHibenrate 3.0:
var max = GetSession.QueryOver<Page>()
.Select(
Projections
.ProjectionList()
.Add(Projections.Max<Page>(x => x.PageOrder)))
.List<int>().First();
If the table is empty you will get max = 0

Session.Query<Page>().Max(x => (int?)x.PageOrder)
Note the cast (I'm assuming PageOrder is an int)

If you are having problems with the QueryOver example by tolism7 (InvalidCastException), here's how I got it working:
var max = session.QueryOver<Page>()
.Select(Projections.Max<Page>(x => x.PageOrder))
.SingleOrDefault<object>();
return max == null ? 0 : Convert.ToInt32(max);

Related

How to write Azure storage table queries for non-existent columns

We have a storage table where we want to add a new integer column (It is in fact an enum of 3 values converted to int). We want a row to be required when:
It is an older row and the column does not exist
It is a new row and the column exists and does not match a particular value
When I just use a not equal operator on the column the old rows do not get returned. How can this be handled?
Update
Assuming a comparison always returns false for the non-existent column I tried somethinglike below (the value of the property will be always > 0 when it exists), which does not work either:
If the (Prop GreaterThanOrEqual -1) condition returns false I assume the value is null.
If not then, the actual comparison happens.
string propNullCondition = TableQuery.GenerateFilterConditionForInt(
"Prop",
QueryComparisons.GreaterThanOrEqual,
-1);
propNullCondition = $"{TableOperators.Not}({propNullCondition})";
string propNotEqualValueCondition = TableQuery.CombineFilters(
propNullCondition,
TableOperators.Or,
TableQuery.GenerateFilterConditionForInt(
"Prop",
QueryComparisons.NotEqual,
XXXX));
Note: The table rows written so far do not have "Prop" and only new rows will have this column. And expectation is the query should return all old rows and the new ones only when Prop != XXXX.
It seems that your code is correct, maybe there is a minor error there. You can follow my code below, which works fine as per my test:
Note: in the filter, the column name is case-sensitive.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference("test1");
string propNullCondition = TableQuery.GenerateFilterConditionForInt(
"prop1", //note the column name shoud be case-sensitive here.
QueryComparisons.GreaterThanOrEqual,
-1);
propNullCondition = $"{TableOperators.Not}({propNullCondition})";
TableQuery<DynamicTableEntity> propNotEqualValueCondition = new TableQuery<DynamicTableEntity>()
.Where(
TableQuery.CombineFilters(
propNullCondition,
TableOperators.Or,
TableQuery.GenerateFilterConditionForInt(
"prop1",//note the column name shoud be case-sensitive here.
QueryComparisons.NotEqual,
2)));
var query = table.ExecuteQuery(propNotEqualValueCondition);
foreach (var q in query)
{
Console.WriteLine(q.PartitionKey);
}
The test result:
Here is my table in azure:

Better query using WHERE IN () when param can be nil

For example we have model TableRow - columns (:account_number, :month, :department, :phone_number). And have a method that returns filtered rows by arrays of this params.
For required params we can use
TableRow.where('account_number IN (?)', param)
Is there best way to add in this query unrequired params (department, phone_number) that can be nill and we should return records with any params in this column?
There are a couple ways to approach this. If you want your query to be static, you can check the literal value of your param with the SQL logic itself:
TableRow.where('COALESCE(:depts) IS NULL OR department IN (:depts)', depts: param)
You can also build up your relation incrementally in Ruby:
relation = TableRow.all
relation = relation.where(department: depts) if depts.present?
Your question is hard to understand, but if what you want is to filter by phone_number while still retrieving records where phone_number is null, you just have to that:
TableRow.where('phone_number IN (?)', param << nil)

Linq Query in VB

Good Day,
I am querying my database using Linq and I have run into a problem, the query searched a column for a search phrase and based on if the column has the phrase, it then returns the results, The query is below,
Dim pdb = New ProductDataContext()
Dim query =
From a In pdb.tblUSSeries
Join b In pdb.tblSizes_ On a.Series Equals b.Series
Where
a.Series.ToString().Equals(searchString) Or
b.Description.Contains(searchString) Or Not b.Description.Contains(Nothing)
Order By b.Series, b.OrderCode Ascending
Select New CustomSearch With
{
.Series = a.Series,
.SeriesDescription= a.Description,
.Coolant = a.Coolant,
.Material = a.Material,
.Standard = a.Standard,
.Surface = a.Surface,
.Type = a.Type,
.PointAngle = a.PointAngle,
.DiaRange = a.DiaRange,
.Shank = b.Shank,
.Flutes = b.Flutes,
.EDPNum = b.EDPNum,
.SizesDescription = b.Description,
.OrderCode = b.OrderCode
}
Return query
I think the problem is that, in the table certain rows are NULL, so when it is checking the column for the phrase and it encounters a row that is null it, breaks and returns this error,
The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
I have ran this query against another column that has all the rows populated with data and it returns the results ok.
So my question is how can I write it in VB to query the db with the supplied searchstring and return the results, when some of the rows in the columns have null values.
Any help would be great.
The exception occurs when you make the projection (i.e. select new CustomSearch)
And yes your trying to assign Null to some int property
(Not sure which one of your properties that is)
one of 2 choices :
1) Use nullalbe types for your properties (or just that one property).
2) project with an inline If ( ?? in C#) , I don't know VB so don't catch me on the syntax.
Taking Series just as an example i don't know if it's an int or if that's the problematic property
Select New CustomSearch With
{
.Series = If(a.Series Is Nothing,0, CInt(a.Series))
}
In C#
Select new CustomSearch
{
Series = a.Series ?? 0;
}

get only one row and one column from table using nhibernate

I have query:
var query = this.session.QueryOver<Products>()
.Where(uic => uic.PageNumber == nextPage[0])
.SingleOrDefault(uic => uic.ProductNumber)
But this query result is type Products. It is possible that result will be only integer type of column ProductNumber ?
Try something like this:
var query = this.session.QueryOver<Products>()
.Where(uic => uic.PageNumber == nextPage[0])
.Select(uic => uic.ProductNumber)
.SingleOrDefault<int>();
Since you need a single primitive type value, you can do .Select to define the result column, and then do .SingleOrDefault to get the only result. For complex types, you'd need to use transformers.
You can find more info about QueryOver in this blog post on nhibernate.info: http://nhibernate.info/blog/2009/12/17/queryover-in-nh-3-0.html
You can use Miroslav's answer for QueryOver, but this would look cleaner with LINQ:
var productNumber = session.Query<Products>()
.Where(uic => uic.PageNumber == nextPage[0])
.Select(uic => uic.ProductNumber)
.SingleOrDefault();
Notice you don't need a cast, as the Select operator changes the expression type to the return type of its parameter (which is the type of ProductNumber).

NHibernate IQueryOver where clause with a collection

I'm attemping to do a simple check for an empty collection in an NHIbernate Query. Here's my code:
var query = QueryNotDeleted().Where(x=>x.Markets.Count() > 0);
QueryNotDeleted returns an IQueryOver. The above line throws an error (Unrecognised method call in epression x.Markets.Count()) because it doesn't recognize the Count() in the query.
I tried
var query = QueryNotDeleted().Where(x=>x.Markets != null);
But unfortunately, Markets is never NULL, so I have to test for a count instead of it being null to get the records I want.
How can I get this "count" syntax correct so that it excludes records where the Markets property is empty?
I was able to get it to work using:
query.RootCriteria.CreateAlias("Markets", "m", JoinType.LeftOuterJoin);
and then
query.RootCriteria.Add(Restrictions.IsNotNull("m.Id"));
If I understand your question correctly you want to get a list of records that don't have corresponding children?
If I wanted to get a list of Orders that have no OrderItems using QueryOver then I would do something like:-
var orders = session.QueryOver<Order>()
.Left.JoinQueryOver(w => w.Items)
.Where(w => w.Order.Id == null);
If this is not the right answer then please can you submit the SQL you are trying to run and the parent/children mappings/.