LINQ to SQL - select query - sql

I need help. I've some types defined:
Class1(){int ID; double Price;}
Class2(){int ID; Class1 myClass1;}
Class3(){int ID; List<Class2> Class2List;}
Now I have a list List<Class3> class3List, from which I need to take only the min double value (the min Price). Is this possible to do with LINQ to SQL, or do I need to use foreach loop?

var min = class3List.SelectMany(x => x.Class2List).Min(x => x.myClass1.Price);
Use SelectMany method to flatten your list of lists List<List<Class2>> into List<Class2>, and then return minimum value in a sequence of prices, fetched by simple selector x => x.myClass1.Price.

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.

LinqToSql: ExecuteQuery an ExecuteQuery-result?

I use this code to get all customers from my database...
Dim customerResult = db.ExecuteQuery(Of VIEW_customers)("SELECT * FROM TOPL_Customers").ToList
Now that I have all customers fetched from the database, I want to run a "filter" query against customerResult - how do I do that?
Was hoping for something like this...
Dim filterResult = customerResult.ExecuteQuery(Of VIEW_customers)("SELECT * WHERE active=1").ToList
Any suggestions? I don't want to query the database twice.
I need to use a string as a search query because it's dynamic.
Thanks
Try this:
var filteredResult = from a in customerResult
//Add suitable filter condition based on column values
where a.Active == 1
select a;
I'm assuming here that VIEW_customers represents your model for the result set.
You can use Expressions to build up a series of filters and then join them together to create a single, dynamic where clause to run against your result set.
Expression<Func<VIEW_customers, bool>> predicate1 = x => x.someField == 'something';
Expression<Func<VIEW_customers, bool>> predicate2 = x => x.otherField == 'something else';
Then you can join them together with .And or .Or as appropriate:
Expression<Func<VIEW_customers, bool>> combinedPredicate = predicate1.And(predicate2);
You can chain any number of these together; it's boolean logic (basically think of each additional clause as being wrapped by a set of parenthesis). When you're ready to consume the predicate, compile it and run it like a normal .Where clause.
Func<VIEW_customers, bool> compiledPredicate = combinedPredicate.Compile();
var results = customerResult.Where(compiledPredicate);

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).

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 to SQL Sum()

select sum(Sales) from WeeklyProductSale.
how i can write this query in linq and what this query will return to me.
thankas in advance.
VB.Net
Dim sumOfSales = Aggregate wps In db.WeeklyProductSale Into Sum(wps.Sales)
You can write it like this,
YourDBContextObject.WeeklyProductSales.Sum(w => w.Sales);
var answer = db.WeeklyProductSales.Sum (s => s.Sales);
This will return a variable of type s.Sales (e.g., decimal).
Edit: if you querying a DataTable, you will need to do this:
myDataTable.AsEnumerable().Sum (row => (decimal) row["Sales"]).
Make sure you reference System.Data.DataSetExtensions.dll and put "using System.Data.DataSetExtensions" into your program because the AsEnumerable extension method that this query uses relies on this. Change (decimal) to the type of the Sales column.