RavenDB: How to query with multiple search terms - ravendb

My entity is:
class Resource
{
string Name;
string EmployeeId;
}
How do I query for resources of multiple employees? I tried this:
Resource[] FindResourcesByEmployees(string[] employeeIds)
{
return this.Session.Query<Resource>()
.Where(r => employeeIds.Contains(r.EmployeeId))
.ToArray();
}
However that gives me NotSupportedException: Method not supported: Contains. Then I tried the following method:
Resource[] FindResourcesByEmployees(string[] employeeIds)
{
return this.Session.Query<Resource>()
.Where(r => employeeIds.Any(v => v == r.EmployeeId))
.ToArray();
}
That throws NotSupportedException: Expression type not supported: System.Linq.Expressions.TypedParameterException.
In SQL it would be something like:
SELECT * FROM resource WHERE employeeid IN (1, 2, 3)
My question is, how do I perform this query in RavenDB?

You can use the In operator. If I remember correctly your code should look like this:
using Raven.Client.Linq;
Resource[] FindResourcesByEmployees(string[] employeeIds)
{
return this.Session.Query<Resource>()
.Where(r => r.EmployeeId.In<string>(employeeIds)))
.ToArray();
}

Related

RavenDB - Adding Index breaks unrelated queries

When I add the index below to my raven database a simple query like
return Session.Query<R>().FirstOrDefault(x => x.RId == Id);
Always returns null. Only after forcing Raven to remove my custom index does desired functionality return. Why is this?
The Index with side effects:
public class RByLatestCommentIndex : AbstractIndexCreationTask<R>
{
public RByLatestCommentIndex()
{
SetMap();
}
void SetMap()
{
Map = r => r.Select(x => new
{
Id = x.Id,
TimeStamp = x.Comments.Count() > 0 ? x.Comments.Max(u => u.Created)
: x.Created
}).OrderByDescending(y => y.TimeStamp).Select(r => new { Id = r.Id });
}
}
public class RIdTransformer : AbstractTransformerCreationTask<R>
{
public RIdTransformer()
{
TransformResults = ids => ids.Select(x => LoadDocument<R>(x.Id));
}
}
EDIT:
In response to Ayende Rahien's comment:
There's a query in the DB which would otherwise be used (Auto/R/ByRID) but the index used looks like this, puzzling enough:
from doc in docs.Rs select new { Images_Count__ = doc.Images["Count()"], RId = doc.RId }
What explains this behaviour? And, will I have to add a static index to be able to query R by RId ?

How can I select the root entity and child entity count using QueryOver in NHibernate?

I have a pretty simple query I'm trying to convert to NHibernate's QueryOver syntax, but I'm having difficulty. The original SQL query is functionally the same as:
SELECT [Post].*, (
SELECT Count(*)
FROM [Comment]
WHERE [Comment].[PostId] = [Post].[Id]) AS [CommentCount]
FROM [Post]
The problem is I'm having difficulty converting this to QueryOver syntax. I tried defining a summary class containing both the Post and the CommandCount as such:
public class PostSummary
{
public Post Post { get; set; }
public CommentCount { get; set; }
}
And then defining the query with a couple of selects:
Post lPostAlias = null;
Comment lCommentAlias = null;
var lCommentSubquery = QueryOver.Of(() => lCommentAlias)
.Where(() => lCommentAlias.Post.Id == lPostAlias.Id)
.ToRowCountQuery();
PostSummary lPostSummaryAlias = null;
session.QueryOver(() => lPostAlias)
.SelectList(list => list
.Select(x => x).WithAlias(() => lSummary.Post)
.SelectSubQuery(lCommentSubQuery).WithAlias(() => lSummary.CommentCount)
.List<PostSummary>();
An exception gets thrown with the error message:
could not resolve property: of: Project.Models.Post
So it looks like it doesn't like the .Select(x => x) part of the query. I was hoping to find something along the lines of 'Projections.RootEntity()` but alas there is no such thing that I can find.
Can someone explain what I'm doing wrong and guide me to the proper way to do this basic query? I imaging I could select all the properties of Post that I want, but worry that I'll lose the ability to take advantage of the proxy sub-classes NHibernate generates for lazy-loading purposes and is not what I want.
using the LINQ provider you can write
var query = from post in session.Query<Post>()
select new PostSummary { Post = post, CommentCount = post.Comments.Count };
return query.ToList();

NHibernate: how to use ExpandoResultTransformer with Session.QueryOver

I have created a ExpandoResultTransformer, that would be used for converting query results to dto to be used in UI. It looks like this:
public class ExpandoResultTransformer : IResultTransformer
{
public object TransformTuple(object[] tuple, string[] aliases)
{
dynamic toReturn = new ExpandoObject();
for (int i = 0; i < aliases.Length; i++)
{
((IDictionary<string, object>)toReturn)[aliases[i]] = tuple[i];
}
return toReturn;
}
public IList TransformList(IList collection)
{
return collection;
}
}
When I use it against a createSQLQuery it works perfectly
var contacts = _session.CreateSQLQuery("exec up_ClientContactsView #ClientId=:clientId")
.SetParameter("clientId", request.ClientId)
.SetResultTransformer(new ExpandoResultTransformer())
.List<dynamic>();
However, when I tried using it against QueryOver, I run into trouble. There are no aliases sent in. So I tried specifying them like this
var periodTables = _session.QueryOver<PeriodTable>()
.Where(x => x.ClientPolicy.Id == request.ClientPolicyId)
.SelectList(list => list
.Select(i =>i.Id).WithAlias(()=>info.PeriodTableId) !! does not work as dynamic cannot be used in expression error
.Select(i => i.Id).WithAlias(()=>"PeriodTableId" !!! does not work either as it cannot find member error
.TransformUsing(new ExpandoResultTransformer())
.List<dynamic>();
Any ideas how to pass in aliases?
You can use an anonymous type instance to act as a template object:
var template = new { PeriodTableId = 0 };
var periodTables = _session.QueryOver<PeriodTable>()
.Where(x => x.ClientPolicy.Id == request.ClientPolicyId)
.SelectList(list => list
.Select(i =>i.Id).WithAlias(()=>template.PeriodTableId)
)
.TransformUsing(new ExpandoResultTransformer())
.List<dynamic>();

Linq To Entity Error while checking the record if exist in database

I am getting an error when trying to use linqsql query:
LINQ to Entities does not recognize the method 'System.String
get_Item(System.String)' method, and this method cannot be translated
into a store expression.
Code:
[HttpPost]
public ActionResult CreateGiftVoucher(FormCollection collection)
{
IVoucherRepository voucherResp = new VoucherRepository();
IQueryable<Voucher> getVoucher = voucherResp.GetAllVouchers();
//if (getVoucher.Where(x => x.Code == collection["Code"]).Count() > 0) {
if (getVoucher.Any(r => r.Code == collection["Code"]))
{
ModelState.AddModelError("Code", "Code Already Exists");
} return View(); }
Voucher Repository
public IQueryable<Voucher> GetAllVouchers()
{
return entity.Vouchers;
}
Your Linq query is translated to SQL, then executed on the database. But there is no SQL equivalent for collection["Code"], so the query can't be translated to SQL, hence the error. In that case the fix is easy: just put the result of collection["Code"] in a local variable outside the query.
string code = collection["Code"];
if (getVoucher.Any(r => r.Code == code))
{
ModelState.AddModelError("Code", "Code Already Exists");
}
LINQ to entities cannot evaluate the expression collection["Code"]. Try evaluating that expression before the query:
string code = collection["Code"];
if (getVoucher.Any(r => r.Code == code))
{
...

How use QueryOver on NHibernate to select custom result

I have this code to return all colors with have some text:
public IEnumerable<Color> FindStartingWith(string term)
{
return Session.QueryOver<Color>().Where(color => color.Name.IsLike(text, MatchMode.Anywhere)).List();
}
But what I want to do, is return a STRING IEnumerable containing only a list of color.Name...
How can I do that with QueryOver?
Thanks
Junio
Syntax may not be exactly right but should be somethign like:
public IEnumerable<string> FindStartingWith(string term)
{
return Session.QueryOver<Color>()
.Select(color => color.Name)
.Where(color => color.Name.IsLike(text, MatchMode.Anywhere))
.List<string>();
}