So, I have the following tables:
Using LLBLGen 2.6 (Adapter Version - No Linq), SQL Server, and .NET 3.5, how would I write the following query?
SELECT o.ObjectID
FROM Object o
INNER JOIN ObjectDetail d ON i.ObjectID = d.ObjectID
WHERE d.CreatedDate = ( SELECT MAX(CreatedDate)
FROM ObjectDetail
WHERE ObjectID = o.ObjectID
)
There will be more filtering, however it's not relevant to this, like if I had an ObjectDetailType and I wanted the max ObjectDetail row for a certain type.
Also, it doesn't have to select o.ObjectID, any / all columns will be fine.
Solved it
PredicateExpression.AddWithAnd(
new FieldCompareSetPredicate(
ObjectDetailFields.CreatedDate,
null,
ObjectDetailFields.CreatedDate.SetAggregateFunction(AggregateFunction.Max),
null,
SetOperator.Equal,
(ObjectFields.ObjectID == ObjectDetailsFields.ObjectID)
)
);
Related
I have this query in Sql Server which I need to consume in EntityFramework, So how can I write a EntityFramwork code which will have the same result as this
WITH cte AS
(
SELECT *
FROM StockGroups
WHERE GroupParent ='Stationery'
UNION ALL
SELECT g.*
FROM StockGroups g
JOIN cte
ON g.GroupParent = cte.GroupName
)
SELECT *
FROM cte
I don't know how to convert it in EF, so I tried with join.
from a in db.StockGroups
join b in db.StockGroups on new { GroupParent = a.GroupParent } equals new { GroupParent = b.GroupName }
where
b.GroupName == "Stationery"
select new {
a.GroupName,
a.GroupParent,
Column1 = b.GroupName,
Column2 = b.GroupParent
}
But the result is not same, as recursive as CTE.
EF does not support recursive CTE's. Use a view or a table valued function.
Getting input from the other experts over SO, I have come up with my own way to achieve this.
IEnumerable<StockGroup> sg = dbContext.ExecuteStoreQuery<StockGroup>(
#"WITH q AS
(
SELECT *
FROM LedgerGroups
WHERE GroupParent = 'Customers'
UNION ALL
SELECT m.*
FROM LedgerGroups m
JOIN q
ON m.GroupParent = q.GroupName
)
SELECT *
FROM q
");
You cannot use CTE recursion in Entity Framework.
Use stored procedure and call that stored procedure through EF
I dont think there is support for recursive CTEs in LINQ nor in EF. The solution is to expose the CTE as a view. The article on Recursive or hierarchical queries using EF Code First and Migrations shows how to deploy such a view using EF code first migrations. Recursive or hierarchical queries using EF Code First and Migrations
Original source:
https://stackoverflow.com/a/11929928/3850405
I've got some C# code with a LINQ query I'm trying to translate to Ruby and am using Sequel as my DB ORM. The linq query just performs some joins and then returns an anonymous object containing references to the joined entities. I've got the code translated and operating correctly but it just returns all of the columns from each table and I'd like to wrap each set of columns up in its own object similarly to how it is done in the C# code.
LINQ Query
from s in slots
join tu in _dbContext.table_usages on s.id equals tu.slot_id
join r in _dbContext.Reservations on tu.reservation_id equals r.ReservationID
join o in _dbContext.orders on r.OrderID equals o.OrderID
join c in _dbContext.Contacts on r.ContactID equals c.ContactID
where tu.reservation_id != null &&
r.state != ReservationStates.Cancelled
select new { SlotId = s.id, Reservation = r, Order = o, Contact = c, TableUsage = tu };
Ruby Code:
select(:slots__id, :reservations.*, :orders.*, :restaurant_customers.*, :table_usages.*)
.filter(slots__restaurant_id: restaurant_id, slots__removed: false)
.filter(slots__slot_time: start_time..end_time)
.join(:table_usages, slot_id: :id)
.join(:reservations, id: :table_usages__reservation_id)
.join(:orders, id: :reservations__order_id)
.join(:restaurant_customers, id: :reservations__contact_id)
.filter('table_usages.reservation_id is not null')
.filter('reservations.state != ?', ReservationStates.cancelled)
I'm unable to find a way of accomplishing this via the docs but I thought I would see if anyone has done something similar in a way that I haven't thought of yet.
Thanks!
I'm assuming you are just referring to the last two lines:
.filter('table_usages.reservation_id is not null')
.filter('reservations.state != ?', ReservationStates.cancelled)
Which you could handle via:
.exclude(:table_usages__reservation_id=>nil)
.exclude(:reservations__states=>ReservationStates.cancelled)
exclude operates as an inverse filter.
I'm trying to force Linq to preform an inner join between two tables. I'll give an example.
CREATE TABLE [dbo].[People] (
[PersonId] [int] NOT NULL,
[Name] [nvarchar](MAX) NOT NULL,
[UpdatedDate] [smalldatetime] NOT NULL
... Other fields ...
)
CREATE TABLE [dbo].[CompanyPositions] (
[CompanyPositionId] [int] NOT NULL,
[CompanyId] [int] NOT NULL,
[PersonId] [int] NOT NULL,
... Other fields ...
)
Now I'm working with unusual database as there's a reason beyond my control for people to be missing from the People table but have a record in CompanyPositions. I want to filter out CompanyPositions with missing People by joining the tables.
return (from pos in CompanyPositions
join p in People on pos.PersonId equals p.PersonId
select pos).ToList();
Linq sees this join as redundant and removes it from the SQL it generates.
SELECT
[Extent1].[CompanyPositionId] AS [CompanyPositionId],
[Extent1].[CompanyId] AS [CompanyId],
....
FROM [dbo].[CompanyPositions] AS [Extent1]
However it's not redundant in my case. I can fix it like this
// The min date check will always be true, here to force linq to perform the inner join
var minDate = DateTimeExtensions.SqlMinSmallDate;
return (from pos in CompanyPositions
join p in People on pos.PersonId equals p.PersonId
where p.UpdatedDate >= minDate
select pos).ToList();
However this now creates a needless where clause in my SQL. As a purest I'd like to remove this. Any idea's or does the current database design tie my hands?
Since PersonId is declared NOT NULL (and I assume it is declared as an FK to People) then I'm not sure how you could have a CompanyPosition with a person that is not assigned; and Linq can't see how you can eiter, which is why as you have observed Linq considers the join redundant.
If you're using LinqToSql, you can use LoadWith similar to this:
var context = new MyDataContext();
var options = new DataLoadOptions();
options.LoadWith<People>(x => x.CompanyPositions);
context.LoadOptions = options;
I don't know how to force linq to use a join. But the following statment should give you the required result.
return (from pos in CompanyPositions
where (p in People select p.PersonId).Contains(pos.PersonId)
select pos).ToList();
ClientSide transformation:
(
from pos in CompanyPositions
join p in People on pos.PersonId equals p.PersonId
select new {pos, p}
).ToList().Select(x => x.pos);
More direct filtering:
from pos in CompanyPositions
where pos.People.Any()
select pos
Is it posible in NHibernate to create a query that looks like this?
select hi.ContactId
From dbo.vw_HostInterests hi INNER JOIN
( Select cm1.ContactId
From dbo.vw_ContactMoments cm1 INNER JOIN
(
Select Contactid
From dbo.vw_ProfileNaw
where GenderId = 1000
) as pn1 on cm1.ContactId = pn1.ContactId
where cm1.ActivityId = 1001
)as cm on hi.ContactId = cm.ContactId
where hi.ActivityId = 1038
I've managed to create the correct output with the IN statement, but I'd realy like the SQL to look like this.
The Criteria below shows part of above query with the IN Statement I used (but want to replace):
ICriteria criteria = DbSession.CreateCriteria<Contact>();
var dCriteria1 = DetachedCriteria.For(typeof(VwHostInterest))
.Add(Expression.Eq("ActivityId", 1038))
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("ContactId")));
var dCriteria2 = DetachedCriteria.For(typeof(VwContactMoment))
.Add(Expression.Eq("ActivityId", 1001))
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("ContactId")));
criteria.Add(Subqueries.PropertyIn("ContactId", dCriteria1));
criteria.Add(Subqueries.PropertyIn("ContactId", dCriteria2));
int count = (Int32)criteria
.SetProjection(Projections.Count("ContactId"))
.UniqueResult();
Probably not the answer you are looking for and apologies if it isn't but my experience is that your best bet with such complex queries would be to:
a) Do this whole thing as a view and map it in NHibernate
b) Create the inner select as a view and create a mapping such that you can relate it in your query
b) Or override nhibernate (override as in skip and not in OO terms ;) and write this as a named query using native SQL.
Does that nested query produce the same result as the following?
SELECT hi.ContactId
FROM dbo.vw_HostInterests hi
INNER JOIN vw_ContactMoments cm1 on hi.ContactId = cm1.ContactId
AND cm1.ActivityId = 1001
INNER JOIN dbo.vw_ProfileNaw pn1 on pn1.ContactId = cm1.ContactId
AND pn1.GenderId = 1000
WHERE hi.ActivityId = 1038
This one has been making my head hurt (which is easy since I'm a NHibernate newbie): how can I represent the following query (T-SQL) through the Criteria API?
DECLARE #pcode VARCHAR(8)
SET #pcode = 'somecode'
SELECT d.*
FROM document d
WHERE EXISTS (
SELECT 1
FROM project p
WHERE p.id = d.projectId AND p.code = #pcode)
OR EXISTS (
SELECT 1
FROM job j INNER JOIN project p ON p.id = j.projectId
WHERE j.id = d.jobId AND p.code = #pcode)
(A Document has two possible associations, Project or Job. Only one of them has a value at a given time; the other has null.)
The goal is to load all Documents that are directly associated with a given Project or indirectly through a Job.
Thanks.
I believe this could do the trick:
DetachedCriteria dCriteria1 = DetachedCriteria.For<Project>("project")
.SetProjection(Projections.Property("project.Id"))
.Add(Restrictions.EqProperty("doc.projectId", "project.Id"));
DetachedCriteria dCriteria2 = DetachedCriteria.For<Job>("job")
.SetProjection(Projections.Property("job.Id"))
.CreateCriteria("Projects", "p")
.Add(Restrictions.EqProperty("doc.jobId", "job.Id"))
.Add(Restrictions.Eq("p.code", "somecode"));
var documents = NHibernateSessionManager.Session.CreateCriteria<Document>("doc")
.Add(Restrictions.Or(
Subqueries.Exists(dCriteria1),
Subqueries.Exists(dCriteria2))).List<Document>();
The above code is derived from the sample query that you provided. If it is not entirely accurate you can change it a bit to make it workable in your solution.