Where clause in NHibernate - c#

How do I express this in NHibernate?
DECLARE #EntityId INT = 800;
SELECT *
FROM UserAlert
WHERE UserAlertId =
(
SELECT MAX(UserAlertId)
FROM UserAlert
WHERE EntityId = #EntityId
)
This is what I'm trying to do.
var senderUA = session.CreateCriteria<UserAlert>()
.Add(Restrictions.Eq("EntityId", id))
.SetProjection( Projections.Max("Id") )
. UniqueResult();
And I keep getting an error that can convert object to UserAlert type, i.e. it's not even compiling.
Thanks for helping

Ordering by UserAlertId descending and selecting top 1 would be simpler.
var senderUA = session.CreateCriteria<UserAlert>()
.Add(Restrictions.Eq("EntityId", id))
.AddOrder(Order.Desc("UserAlertId"))
.SetMaxResults(1)
.UniqueResult();
Additionally you can
var senderUA = session
.Query<UserAlert>()
.Where(x=>x.EntityId==id &&
x.UserAlertId==session.Query<UserAlert>()
.Where(x=>x.EntiryId==id).Max(x=>x.UserAlertId)
).FirstOrDefault();

Here's a solution using QueryOver.
var maxUserAlertId = QueryOver.Of<UserAlert>
.Where(ua => ua.EntityId == id)
.Select(
Projections.Max(
Projections.Property<UserAlert>
(u => u.UserAlertId)
)
);
var maxUserQuery = session
.QueryOver<UserAlert>()
.WithSubquery
.WhereProperty(u => u.EntityId)
.Eq(maxUserAlertId);
// Dealing with the situation that the maximum value is shared
// by more than one row. If you're certain that it can only
// be one, call SingleOrDefault instead of List
IList<UserAlert> results = maxUserQuery.List();

Related

Linq:How to write Any in query syntax?

IEnumerable<Gruppe> cand = (IEnumerable<Gruppe>)populations.Where(
x => !x.Attributes.Any(
y => y.GetType() == typeof(Arbeit)
)
);
I wondered how I could write the above in query syntax but stumbled because of the Any method.
There is no equivalent of Any in query syntax. So the best you can do is:
IEnumerable<Gruppe> cand =
from population in populations
where !population.Attributes.Any(y => y.GetType() == typeof(Arbeit))
select population
(I'm assuming that the cast to IEnumerable<Gruppe> is not necessary. If that assumption is wrong, you will need to add it back.)
The Any could be refactored out, but you are still going to need a Count.
var cand = from population in populations
let attributeCount = population.Attributes.Count
let validAttributeCount = (
from attribute in population.Attributes
where attribute.GetType() != typeof(Arbeit)
select attribute
).Count()
where attributeCount == validAttributeCount
select population;
I like Svik's answer.
Another way to put it is like this:
IEnumerable<Gruppe> cand =
from population in populations
where ( from attribute in population.Attributes
where attribute.GetType() == typeof(Arbeit)
select true).Any() == false
select population

How can generate a sequence number inside a LINQ select?

I am getting a hard time generating a sequence number for my list using Linq Select.
I tried to use a normal variable i then increment it inside but it's not working.
var grouped = (from x in jOMACDetails
group x by new { x.MAWorkCode, x.ConstructionNumber } into g
let f = g.First()
select new UtilityReceivingReportDetailEntity
{
DefaultAccountCode = string.IsNullOrWhiteSpace(f.AccountTitleCode) ? f.AccountTitleName.Trim() : f.AccountTitleCode.Trim(),
CompanyID = CurrentContext.CurrentCompanyID,
RRNumber = socnumber.Trim(),
RRSequenceNumber = (short)???, // <---- Here is the container the I need to be sequence
//...............
}).AsEnumerable();
can someone help me about this?
thanks in advance
You can try Select() overload which projects each element of a sequence into a new form by incorporating the element's index automatically:
var grouped = jOMACDetails.GroupBy(x => new { x.MAWorkCode, x.ConstructionNumber })
.Select(g => g.First())
.Select((r, index) => new UtilityReceivingReportDetailEntity
{
DefaultAccountCode = string.IsNullOrWhiteSpace(r.AccountTitleCode) ? r.AccountTitleName.Trim() : r.AccountTitleCode.Trim(),
CompanyID = CurrentContext.CurrentCompanyID,
RRNumber = socnumber.Trim(),
RRSequenceNumber = index
})
.AsEnumerable();
Sadly, there is not any query expression which uses that overload. So, I wrote my answer in method syntax. But, you can use .Select after finishing your query expression if you wish. But, IMHO there is no need.
You´re looking for this?
var i = 0;
var grouped = (from x in jOMACDetails
group x by new { x.MAWorkCode, x.ConstructionNumber } into g
let f = g.First()
select new UtilityReceivingReportDetailEntity
{
DefaultAccountCode = string.IsNullOrWhiteSpace(f.AccountTitleCode) ? f.AccountTitleName.Trim() : f.AccountTitleCode.Trim(),
CompanyID = CurrentContext.CurrentCompanyID,
RRNumber = socnumber.Trim(),
RRSequenceNumber = i++
}).AsEnumerable();

Entity Framework Query Nested Query

I am new to the entity framework and am trying to convert the following query into the correct function calls.
Select Distinct a.nodeId FROM
(SELECT *
FROM reportContents
Where fitId = '29' and reportId =
(select max(reportId)
from reportContents
where fitId = '29')
) a Where (a.nodeId IS NOT NULL)
I know this query does what i want, however i'm not sure how to translate that into the entitiy framework!
Here was my attempt.
var prevSelectedNodes = db.reportContents.Where(
f => f.fitId == id).Select(
f => f.nodeId).Distinct().ToList();
I need to somehow put a .Select() in the where call. However that kind of thing dosen't seem possible
Thank you in advance!
As you can't make two LINQ nested lambda expression. You can do it with two requests :
var maxReportId = db.reportContents.Where(r => r.fitId = "29").Max(r => r.RepordId);
var result = db.reportContents.Where(r => r.fitId == "29" && r.reportId == maxReportId && r.nodeId != null).Select(a => a.nodeId).Distinct().ToList() ;

Adding a where/order by clause to an IQueryable

I have ths function to query a set of records from the DB:
public IQueryable<PointTransactionViewModel> GetPointTransactions(int UserID)
{
return
(
from PointTransaction p in entities.PointTransaction
join ActivityLog a in entities.ActivityLog
on p.TransactionID equals a.TransactionID
where p.UserID == UserID
select new PointTransactionViewModel
{
ID = p.TransactionID,
Balance = p.Balance,
Points = p.Amount,
RelatedActivityID = a.ID,
When = p.When,
Sender = p.SenderUserInfo.CompleteName
}
);
}
I wish to add an additional cause, like this
var entries = GetPointTransaction(1);
return entries.OrderbyDescending.Where( x => x.When >= start && w.When <= end).
( x => x.When);
However, I seem to need to create a new query from the existing one for this to work. But, I have seem this work before without creating a new query, in the code snippet before:
public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = source.Count();
TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
}
Does the code above somehow doesn't need a new query to be created for the IQueryable source object? Was a temporary object created?
Edit
It's strange, but to get it to work I have to do the following:
IQueryable<ActivityLogEntry> log = activityRepo.GetPointTransaction(userID).
Where(x => x.PointsEarned == 50);
return log.ToList();
The following will not work:
var log = = activityRepo.GetPointTransaction(userID);
log.Where( x => x.PointsEarned == 50);
return log.ToList();
There is no error message, just that the where clause seems to be ignored (it is also returning all data which PointsEarned is not 50)
Your entries is of IQueryable type, that's enough and you can add any number of clauses before fetching the data, e.g. before calling the ToList() function.
It doesn't execute the SQL code, just an expression tree will be created until you fetch the whole data with one of the existing methods (again, e.g. the ToList() function).
var query = context.Where(x=>x.id == test);
query = query.Where(anotherCondition1);
query = query.Where(anotherCondition2);
...
var result = query.ToList();
it's equal to
var result = context.Where(x=>x.id == test)
.Where(anotherCondition1)
.Where(anotherCondition2)
....
.ToList()
This is called deferred execution, for more details see the MSDN blog post on LINQ and Deferred Execution.
You do need to create a new object. IQueryable is immutable. Don't worry this is how you are supposed to do it. This is how the queries are formed internally. All the extension methods like "Where" don't actually change the object. They just return a new one.
The code that you claim works should not work. The method doesn't even have a type.
i mean you can write this sample :
opportunites = from opp in oppDC.Opportunities
join org in oppDC.Organizations on opp.OrganizationID equals org.OrgnizationID
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
if(condition)
{
opportunites = opportunites.Where(opp => opp.Title.StartsWith(title));
}
//------Other Condition you need
if(!String.IsNullOrEmpty(title))
{
opportunites = opportunites.Where(.....);
}
if(!String.IsNullOrEmpty(name))
{
opportunites = opportunites.Where(.....);
}
As others have pointed out, you do not need a new object. Your syntax for OrderByDescending is wrong though, you need to specify the key selector.
var entries = GetPointTransaction(1);
return entries.Where(x => x.When >= start && w.When <= end).OrderbyDescending(x => x.When);

Linq - Retrieve a single value in a String

I use Asp.net 3.5 and EF 4.
I need find a specific row in my DataBase and display on a label a single value as string.
At the moment I use this code, it is working, so I find a single Object and read its properties.
var myAuthor = (from at in context.CmsAuthors
where at.AuthorId == myRow.AuthorId
select at).Single();
myAuthorNameLabel.Text = myAuthor.LastName;
I would like to know:
If there is another syntax in Linq to achieve the same result.
How to do it using Lamba?
Which approach would you suggest me?
Here's the method syntax (using lambdas)
myAuthorNameLabel.Text = context.CmsAuthors
.Where(at => at.AuthorId == myRow.AuthorId)
.Select(at => at.LastName)
.SingleOrDefault() ?? string.Empty;
You can use:
var myAuthorName =
(from at in context.CmsAuthors where at.AuthorId == myRow.AuthorId select at).Single().Select(a => a.LastName);
actually this would be even better:
var myAuthorName =
(from at in context.CmsAuthors where at.AuthorId == myRow.AuthorId select at).Select(a => a.LastName).Single();
Update
An example of how to use with Anonymous type:
var myAuthorNames =
(from at in context.CmsAuthors where at.AuthorId == myRow.AuthorId select at).Select( a => new {a.LastName, a.FirstName}).Single();

Categories