get only one row and one column from table using nhibernate - 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).

Related

How can I use a method to add a filter on a property in Entity Framework Core?

I need to conditionally add a filter to particular dates in a query. There are common preconditions and the filter will be the same. Therefore I would like the common code to be in a method which can perform these checks and then have the consumer pass in the property which the filter should be applied to (could be applied to multiple).
Here is a simplified version of my code.
var query = dbContext.Documents.AsQueryable();
query = FilterDocumentsByDate(query, x => x.CreatedDate);
query = FilterDocumentsByDate(query, x => x.SubmittedDate);
private IQueryable<Document> FilterDocumentsByDate(IQueryable<Document> query, Func<Document, DateTime> propertyToSearch)
{
query = query.Where(x => propertyToSearch(x).Year > 2000);
return query;
}
When I look at the query in SQL profiler, I can see that the query is missing the WHERE clause (so all documents are being retrieved and the filter is being done in memory). If I copy/paste the code inline for both dates (instead of calling the method twice) then the WHERE clause for the both dates are included in the query.
Is there no way to add a WHERE condition to an IQueryable by passing a property in a Func which can be properly translated to SQL by Entity Framework?
EF is unable to understand your query, so it breaks and executes WHERE clause in memory.
The solution is creating dynamic expressions.
var query = dbContext.Documents.AsQueryable();
query = FilterDocumentsByDate(query, x => x.CreatedDate.Year);
query = FilterDocumentsByDate(query, x => x.SubmittedDate.Year);
private IQueryable<Document> FilterDocumentsByDate(IQueryable<Document> query, Expression<Func<Document, int>> expression)
{
var parameter = expression.Parameters.FirstOrDefault();
Expression comparisonExpression = Expression.Equal(expression.Body, Expression.Constant(2000));
Expression<Func<Document, bool>> exp = Expression.Lambda<Func<Document, bool>>(comparisonExpression, parameter);
query = query.Where(exp);
return query;
}
I am sorry, I haven't run this myself, but this should create WHERE statement. Let me know how it goes.

Querying distinct with MongoMapper

How do I query distinct with MongoMapper? My query is:
subscribedToThread = Comment.where(:subscribe_thread => 1).all
But this will return many objects with the same user_id. I need to return just a distinct user_id. Is this possible?
I think you will need to drop down to the ruby driver in order to do this as I don't think you can do this with MongoMapper itself:
subscribedToThread = Comment.collection.distinct("user_id", {:subscribe_thread => 1})
Calling the collection method on a model returns the collection as would be provided by the Ruby driver directly so you can issue a distinct query using the syntax below:
collection.distinct(key, query = nil)
You can read more about it here
Yes, you can do so:
subscribedToThread = Comment.where(:subscribe_thread => 1).fields(:user_id).all.compact!.unique!
This will nil every field but user_id which you then uniq!,ie you remove all doubles and then compact! all nil
http://mongomapper.com/documentation/plugins/querying.html#fields
Try this
subscribedToThread = Comment.where(:subscribe_thread => 1).fields(:user_id).collect(&:user_id).uniq
It will show you list of uniq user_id

Truncate DateTime in NHibernate QueryOver SelectGroup

I have a fairly run-of-the-mill QueryOver query containing the following,
.SelectList(list => list
.SelectGroup(() => txn.GroupField)
.SelectGroup(() => txn.Date))
.List<object[]>()
This query works as expected however I now have a requirement to group by the truncated Date as some of the Date's for these objects may contain a time component. This seems like it should be a trivial change but I can't find a way that is supported by NHibernate.
The obvious solution would be the change below but is not supported.
.SelectGroup(() => txn.Date.Date))
Any ideas?
Thanks
Your QueryOver could look like this:
Status alias = null;
var query = QueryOver.Of(() => alias)
.Select(Projections.GroupProperty(
Projections.SqlFunction("date", NHibernateUtil.Date, Projections.Property(() => alias.Date))));
Output (pseudo sql):
SELECT
...
FROM [Status] this_
GROUP BY dateadd(dd, 0, datediff(dd, 0, this_.Date))
Hope this helps, cheers!
You might want to add a helper property to your map, using the Formula command, to be able to use the date (instead of datetime) in queries.
here's an example from my code; it uses a decimal value, but this works fine with any subquery:
model class has this property, to be mapped to a formula:
public virtual decimal Profit
{
get { return this.SellPrice - this.Cost; }
set { return; }
}
fluentNHibernate map:
//SellPrice and Cost are columns in the object's table
Map(v => v.Profit).Formula("(SellPrice - Cost)"); // this field is calculated, not read
be sure to put the formula between () brackets though.
If you'd make your formula a select query that trunks the datetime into a date, you could then group by that property in your query.

How can I select the maximum value in 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);

Linq.Where-to-SQL on a text field comparing to a list of values

Customer.text is a field in an T-SQL DB (that I do not control and thus may not alter) of type "text".
I'd like to do something like this:
List<string> compare = new List<string>();
compare.Add("one");
compare.Add("two");
var q = from t in customer
where t.text.Contains( compare.First())
select t;
this will work.
But now I'd like to do something like: (!NOT WORKING!)
var q = from t in customer
where compare.Contains( t.text )
select t;
How can I achieve this? Is it even possible?
EDIT: The problem is obviously not exactly clear: A text column in SQL cannot be queried using "=" but only with LIKE. Thus the compare.Contains( t.text ) will result in an error, as it is converted into a query using "=".
What I did not tell - I thought it is irrelevant - is, that I use LINQ-to-ORM (LLBLGen in this case).
What I tried instead:
var q = from t in customer
where compare.Any( x => t.text.Contains(x) )
select t;
Now this did not work also. Currently I'm not at work, but the exception was something with a ConstantExpression not being convertable into a SetExpression.
I hope this gave some clarification.
EDIT2:
Joseph pointed this out to me: PredicateBuilder. It creates an Expression on a given ObjectType.
Now my problem is, that my type is an anonymous type out of multiple joins.
Is there an easy or elegant way to handle this?
Now I might be missing something, but your code looks like it should work. Did you include the namespaces at the top of the file?
using System.Linq;
using System.Linq.Expressions;
You could also rewrite it without the Linq2Sql syntax, like:
var q = customer.Where(c => compare.Contains(c.text));
You could build your query using LinqKit's free predicate builder class. Here is a blog post which describes its use and has a link to the download site.
http://thecodeslinger.wordpress.com/2008/10/28/linqkit-predicatebuildert-goodness/
Below is a code sample from the post
//First get a list of keywords that match the description entered.
string[] parts = txtInclude.Text.Split(new[] {‘ ‘});
string[] noparts = null;
if(txtButNot.Text.Trim().Length > 0)
noparts = txtExclude.Text.Trim().Split(new[] {‘ ‘});
var pred = PredicateBuilder.True<Pet>();
//here is where you would loop through your compare object
parts.ForEach(p => pred = pred.And(pl => pl.description.Contains(p)));
if(noparts != null)
noparts.ForEach(p => pred = pred.And(pl => !pl.description.Contains(p)));
var pets = from s in db.Pets.Where(pred)
select s;
You have to convert the text field to string
var query = from t in dataContext.table
where compare.Contains(t.textField.ToString())
select t;