I'm trying to get all active tasks from an employee by QueryOver and RowCount with this code:
var id = 1;
var activeTasks = Session
.QueryOver<Employee>()
.Where(emp => emp.id == id)
.JoinQueryOver<Tasks>(emp => emp.Tasks, JoinType.InnerJoin)
.Where(task => task.State == TaskState.Active)
.RowCount();
If there is no employee with the specified id, RowCount() returns 0.
The thing is I need to know if the employee didn't exist or if there was no active tasks.
I could do this with 2 queries where I would first get the employee and check for null, then query for the tasks. But ideally if it's possible I would want this to go all in one query.
You can do it much simpler with LINQ to NHibernate:
var employeeWithActiveTaskCount = session
.Query<Employee>()
.Where(e => e.Id == id)
.GroupJoin(
session
.Query<Task>()
.Where(t => t.State == TaskState.Active),
e => e.Id,
t => t.Employee.Id,
(e, t) => new { Employee = e, Tasks = t })
.Select(et => new
{
EmployeeId = et.Employee.Id,
TaskCount = et.Tasks.Count()
});
This will return only existing employees with appropriate number of tasks. In case the employee doesn't exist, empty collection is returned. The query generated by this looks as follows:
select employee0_.Id as col_0_0_, (select cast(count(*) as INT)
from [Task] task1_ where task1_.State=?
and (task1_.Employee_id=employee0_.Id
or (task1_.Employee_id is null)
and (employee0_.Id is null)))
as col_1_0_ from [Employee] employee0_ where employee0_.Id=?
Related
I'm trying to create a statement in where i start out with an ID to select an object in table1, then take 2 new ids from that object and using them to look up 2 different objects in table2.
My goal is to end up with an anonymous object that has the object from table1 and the 2 objects from table2 i.e. (table1.object, table2.object1, table2.object2).
I don't know if this can be done in a single statement or not.
So far I got this, but it only gives me table1.object and table2.object1, and not table2.object2:
db.Person.Where(x => x.Id == myId)
.SelectMany(p => db.OtherPerson
.Where(o=> p.OhterP1_Id1 == o.Id).DefaultIfEmpty(),
(p, o) => new {pers = p, otherP = o})
This is what you want:
var result = db.Person.Where(x => x.Id == myId)
.Select(p => new {
pers = p,
otherP1 = db.OtherPerson.SingleOrDefault(o => p.OhterP1_Id1 == o.Id),
otherP2 = db.OtherPerson.SingleOrDefault(o => p.OhterP1_Id2 == o.Id)
}).SingleOrDefault();
I've been trying to turn a fairly basic piece of SQL code into Lamda or Linq but I'm getting nowhere. Here is the SQL query:
SELECT * FROM Form a
INNER JOIN FormItem b ON a.FormId = b.FormId
INNER JOIN FormFee c ON a.FormId = c.FormId
INNER JOIN FeeType d ON c.FeeTypeId = d.FeeTypeId
WHERE b.StatusId = 7
I tried this but it isn't doing what I want.
public Form GetFormWithNoTracking(int id)
{
return ObjectSet
.Where(x => x.FormId == id &&
(x.FormItem.Any(di => di.StatusId == (short)Status.Paid)))
.AsNoTracking()
.FirstOrDefault();
}
I'm trying to return only the rows from FormItem whose StatusId is Paid. However, the above returns all. I know that .Any() will check if there are any matches and if there are return all, so in this case my data, for this form, does have items who have a StatusId of Paid and some items whose StatusId is not paid so it brings back them all.
var query = (from a in ObjectSet.FormA
join b in ObjectSet.FormB on a.field equals b.field
where b.StatusId = 7
select new { a, b})
You can join rest with same logic.
This should be what you are asking for:
Get the Form with FormId = id
Of that form, return all FormItems that have StatusId = Paid
public IEnumerable<FormItem> GetFormWithNoTracking(int id)
{
return ObjectSet
.SingleOrDefault(x => x.FormId == id)
.Select(f => f.FormItem
.Where(di => di.StatusId == (short)Status.Paid))
.AsNoTracking();
}
If you need the Form itself too, you might want to create a custom type (edit: see #Burk's answer) or return a Tuple<Form,IEnumerable<FormItem>>, a IEnumerable<Tuple<Form,FormItem>> or whatever suits your needs best instead.
Alternatively you could remove all non-paid items of the form.
public Form GetFormWithNoTracking(int id)
{
var form = ObjectSet
.SingleOrDefault(x => x.FormId == id)
.AsNoTracking();
var nonPaid = form.Select(f => f.FormItem
.Where(di => di.StatusId != (short)Status.Paid)).ToList();
foreach(FormItem item in nonPaid)
form.FormItem.Remove(item);
return form;
}
How do fetch data from multiple tables with method syntax without using joins, but only .where() methods?
I'm making a select against EF5 db context which maps to this legacy table structure where I have a persons detail table and another table which refers both to itself to create a hierarchy and to the person details table this way:
PersonSet
.Where(p => p.LastName.ToLower()=="surname")
.Join(SubsetSet, p => p.Id, ss => ss.SubsetLink, (p, ss) => new { PersonDetail = p, person = ss })
.Where(m => m.person.Frame=="a" && m.person.Purpose=="1")
.Join(SubsetSet, ss1 => ss1.person.Owner, person => person.SubsetLink, (ss1, ss2) => new { person = ss1, club = ss2 })
.Where(a => a.club.Frame=="b" && a.club.Purpose=="2")
.Join(SubsetSet, ss => ss.club.Owner, ss2 => ss2.SubsetLink, (ss, ss2) => new { club = ss, association = ss2 })
.Where(a => a.association.Frame=="b" && a.association.Purpose=="3")
.Join(SubsetSet, ss => ss.association.Owner, ss3 => ss3.SubsetLink, (ss, ss3) => new { association = ss, district = ss3})
.Where(d => d.district.Frame=="b" && d.district.Purpose=="4" && d.district.SubsetLink=="12345")
.Select(proj => new { proj.association.club.person, proj.association.club, proj.association, proj.district })
.OrderByDescending(a => a.association.club.person.phyperson.FirstName)
.Take(10).Dump();
The above query works at least in LinqPad but, it seems to me that If I could get rid of those joins the statement might look a bit nicer. Now I know, like in the Albahari example below, that this can be done with query syntax. But I couldn't find an example that would illustrate this situation with method syntax. The way I'm trying to approach this might of course be wrong and that's why I can't find suitable examples.
Here I found something similar, but couldn't make it work in LinQPad:
Is multiple .Where() statements in LINQ a performance issue?
Or this one, where the solution is again in query syntax:
Cross Join with Where clause
Or this example by Albahari: (http://www.linqpad.net/WhyLINQBeatsSQL.aspx)
from p in db.Purchases
where p.Customer.Address.State == "WA" || p.Customer == null
where p.PurchaseItems.Sum (pi => pi.SaleAmount) > 1000
select p
Consider this query:
var q = from order in orders
from orderline in order.Lines
where orderline.Count > 10
select order.Discount * orderline.Price;
this more or less corresponds to
var q = orders
.SelectMany(order => order.Lines, (order, orderline) => new { order, orderline})
.Where(item => item.orderline.Count > 10)
.Select(item => item.order.Discount * item.orderline.Price);
For more information on SelectMany, see the MSDN documentation.
If you don't have associations defined:
var q = from order in orders
from orderline in orderLines
where orderline.OrderId == order.Id
where orderline.Count > 10
select order.Discount * orderline.Price;
this more or less corresponds to
var q = orders
.SelectMany(order => orderLines, (order, orderline) => new { order, orderline})
.Where(item => item.orderline.OrderId == item.order.Id)
.Where(item => item.orderline.Count > 10)
.Select(item => item.order.Discount * item.orderline.Price);
I have table with 10 000 elements.
IQuerable<IEntity> query = dataRep.Get<IEntity>()
.Query();
I need to get the index(rownum) of selected obj without getting all table items
var obj = query.Where( x => x.Name == "testName")
.FirstOrDefault();
The simple sql work fine :
select name, id, r from
(
select name, id, rownum r from collections order by id
) where name = 'testName';
How do this in Linq to NHibernate ?
Edit:
I tried add to IEntity class property RowNumber and mapping this on hbm as
<property name="RowNumber" formula="rownum" />
But after
var index = query.Where( x => x.Name == "testName")
.Select( x => x.RowNumber)
.FirstOrDefault();
Get always 1 value
Can you not just filter the query directly?
IQuerable<IEntity> query = dataRep.Get<IEntity>()
.Query()
.FirstOrDefault(x => x.Name == "testName");
Edit:
To get the item you can project into an anonymous type:
var query = (from data in dataRep.Get<IEntity>().Query()
where Name == "testName"
select new
{
id = data.id,
rowNumber = data.rowNumber
}).FirstOrDefault();
I'm have a SQL statement which I am trying to transform in a LINQ statement...
SELECT DISTINCT mc.*
FROM ManufractorCategories mc
WHERE mc.Active = 'true'
AND mc.Folder = 'false'
AND (mc.Id not in (SELECT Category_id FROM Manufractor_Category
WHERE Manufractor_id = 3));
That's my last, not working LINQ statement
(IQueryable<object>)db.ManufractorCategories
.Where(o => o.Active == active)
.Where(o => o.Folder == folder)
.Select(i => new { i.Id, i.Folder }).Except(db.Manufractor_Categories.Where(t => t.Manufractor_id == id).Select(t => new { t.Category_id })).Distinct();
I've tried the whole Sunday on that, but the Except statement won't work.
Thanks in advances for any help!
The Except method requires two sets of the same type - this means that you would have to select objects of type ManufractorCategory in the nested query as well as in the outer query - then it would select all categories that are in the first one and not in the second one.
An easier alternative is to use the Contains method to check whether the current ID is in a list of IDs that you want to filter. The following should work:
var q =
db.ManufractorCategories
.Where(o => o.Active == active)
.Where(o => o.Folder == folder)
.Select(i => new { i.Id, i.Folder })
.Where(o =>
!db.Manufractor_Categories
.Select(t => t.Manufractor_id)
.Contains(o.Id)
.Distinct();
And a simplified version using query syntax:
var q =
from o in db.ManufractorCategories
where o.Active == active && o.Folder == folder &&
db.Manufractor_Categories
.Select(t => t.Manufractor_id)
.Contains(o.Id)
select new { i.Id, i.Folder };
The Except statement is going to get a list of objects with the Category_id property. However, you're query has a result that contains objects with the Id and Folder properties. The query will most likely be unable to see where these objects are equal, and so, the Except clause won't take effect.