I have a query like this
var errorLogs = db.ErrorLogs.Include(e => e.Inventory);
return View(await errorLogs.ToListAsync());
The Inventory Contain a field named CreatedBy
I want to add a where clause on this field how can I do it?
If it is on the Inventory table, then it should be something like the following
var errorLogs = db.ErrorLogs.Include(e => e.Inventory).Where(el => el.Inventory.CreatedBy == "Sanjoy");
Related
I am using NHibernate to fetch data form SQL Server.
To get data I wrote var result = Repository.QueryOver<table_reference>().Where(c => c.Amount >100).List()
Now I want to get result filtered by foreign key reference something like
Repository.QueryOver<TaxInvoicePassing>().Where(c => c.Branch.Employee.Salary > 10000).List()
How can I achieve this?
One way is iterate for each table's record and then addrange of results
Thanks in advance
Using QueryOver, you can try this:
// declare the alias
Branch branch = null;
Employee employee = null;
Session.QueryOver<TaxInvoicePassing>() // get a queryOver of TaxInvoicePassing
.JoinAlias(t => t.Branch, () => branch) // add a join with Branch
.JoinAlias(() => branch.Employee, () => employee) // add a join with Employee
.Where(c => employee.Salary > 10000) // add where filter on employee's salary
.List();
Using Linq, it could be done like the expression you asked:
Session.Query<TaxInvoicePassing>()
.Where(c => c.Branch.Employee.Salary > 10000) // this expression will be converted on a join
.List();
I would move these queries inside the repository object instead exposing it.
I am current having an issue with getting records from database using nhibernate.
My 'publicstring' column is having two values, one with lower case and the other with upper case.
I am trying to fetch one of them depending on what is typed.
Below is my query
private string _publicId;
var _mediaFileShare = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.Publicsting == _publicstring)
.SingleOrDefault();
Answers would be appreciated..
A naive solution is:
var _mediaFileShare = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.PublicString == _publicString)
.List()
.SingleOrDefault(r => string.Compare(r.PublicString, _publicString, StringComparison.Ordinal) == 0);
If you're confident that the query will always return two rows then performance should be very acceptable. Alternatively you could use a dynamic order by, something like:
var query = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.PublicString == _publicString);
query = _publicString == _publicString.ToLower()
? query.OrderBy(q => q.PublicString)
: query.OrderByDescending(q => q.PublicString);
var _mediaFileShare = query.Take(1).SingleOrDefault();
The results using an order by will be dependent on your database and its collation setting.
I have a main VendorProfile table and a 1-many VendorHistory table that contains status codes and date stamps. The query below works at retrieving only the latest status (status code and date) for each vendor. However, the view allows the user to select checkboxes of any of the status codes to filter the view. So I need to add a where clause that matches ANY of the checkbox StatusSelections.
Model Diagram
public IEnumerable<BrowseStatusModel> BrowseByStatus(int[] StatusSelections)
{
IQueryable<BrowseStatusModel> query = _db.VendorProfiles
.Include("VendorStatusHistory")
.Include("StatusCodes")
.Select(s => new BrowseStatusModel
{
ProfileID = s.ProfileID,
Name = s.Name,
CompanyName = s.CompanyName,
CompanyDBA = s.CompanyDBA,
DateCreated = s.DateCreated,
Status = s.VendorStatusHistories.OrderByDescending(o => o.DateCreated).FirstOrDefault().Id,
StatusDate = s.VendorStatusHistories.OrderByDescending(o => o.DateCreated).FirstOrDefault().DateCreated
})
.OrderBy(x => x.ProfileID);
foreach (int status in StatusSelections)
{
query = query.Where(x => x.Status == status);
}
return query;
}
The above foreach loop works but, unfortunately creates AND condition where ALL selections must be true instead of ANY. I figured I would have to use a where clause with the following in some way but have been unsuccessful at the correct syntax.
.AsQueryable().Any();
Use contains in the place of that foreach loop
query = query.Where(x => StatusSelections.Contains(x.Status))
I have a small problem with multiple instances of the same object after a join to an other table. For testing I create one Store with two Products (ManyToMany-Relation). The following snippet hopefully describes my problem.
var preResult = _session.QueryOver<Store>().List(); // One store
Product productAlias = null;
var result = _session.QueryOver<Store>()
.JoinAlias(s => s.Products, () => productAlias)
.List(); // Two instances of the same store
I even think this behavior is correct but how can I prevent the multiple instances? Is it possible within the query?
Just for information why I need to make this unnecessary join: I want to extend the query according to different critirias, similar to this:
Product productAlias = null;
var query = _session.QueryOver<Store>().JoinAlias(s => s.Products, () => productAlias);
if (!string.IsNullOrWhiteSpace(criteria.ProductName))
{
query.Where(Restrictions.On(() => productAlias.Name).IsInsensitiveLike(criteria.ProductName));
}
if (criteria.ProductType != null)
{
query.Where(s => productAlias.Type == criteria.ProductType);
}
var result = query.List();
Here I ran into different problems, depending on the criterias.
Try using Transformers.DistinctRootEntity in your scenario to eliminate the cartesian product.
Product productAlias = null;
var query = _session.QueryOver<Store>()
.JoinAlias(s => s.Products, () => productAlias)
query = query.TransformUsing(Transformers.DistinctRootEntity);
var result = query.List();
Let's split solution into two queries.
Top one QueryOver<Store>() will be correctly returning just a distinct list. And what's more, by design it will support paging (Take(), Skip()).
The inner one, will be returning just a list of Store IDs, which fully meet whatever criteria...
The result SQL will look like this
SELECT ... // top one
FROM Store
WHERE StoreID IN ( SELECT StoreID ...) // inner one
Inner
Let's start with the inner select, the NHibernate detached QueryOver:
Store storeAlias = null;
Product productAlias = null;
// detached query, resulting in a set of searched StoreID
var subQuery = QueryOver.Of<Store>(() => storeAlias)
.JoinAlias((s) => s.Products, () => productAlias)
.Select((s) => s.ID); // ID projection
if (!string.IsNullOrWhiteSpace(criteria.ProductName))
{
subQuery.Where(Restrictions.On(() => productAlias.Code)
.IsInsensitiveLike(criteria.ProductName));
}
Top
Once we have filtered the Store we can use this subquery in top one
var query = session.QueryOver<Store>()
// IN clause
.Where(Subqueries.PropertyIn("ID", subQuery.DetachedCriteria))
.Skip(100)
.Take(50) // paging over already distinct resultset
;
var result = query.List<Store>();
And now we can apply whatever filter to inner query, and get list of Store IDs which do meet filter criteria... while working with top query, which is distinct...
I would like to make this query:
Session.Linq<User>().Where(u => u.Payments.Count(p => p.Date != null) > 0);
In plain English I want to get all the users that has at least one payment with the date specified.
When I run the sample code I get a System.ArgumentException with the message:
System.ArgumentException : Could not find a matching criteria info provider to: this.Id = sub.Id
Do you know a solution to this problem?
It would also be very helpful if someone could provide the same query with the NHibernate Query by Criteria API.
I'm not sure if this will work in your particular case, but I would use the .Any() extension to clean up the linq query a bit; for example:
Session.Linq<User>().Where(u => u.Payments.Any(p => p.Date != null));
I think something like it:
Customer customerAlias = null;
criteria = CurrentSession.CreateCriteria(typeof(User), () => customerAlias);
if (searchCriteria.OrdersNumber.HasValue)
{
ICriteria paymentsCriteria = criteria.CreateCriteria<Customer>(x => x.Payments);
DetachedCriteria paymentsCount = DetachedCriteria.For<Payment>();
paymentsCount.SetProjection(Projections.RowCount());
paymentsCount.Add(SqlExpression.NotNull<Payment>(x => x.Date));
paymentsCount.Add<Payment>(x => x.Customer.Id == customerAlias.Id);
paymentsCriteria.Add(Subqueries.Gt(1, paymentsCount));
}
return criteria.List<User>();