var transactions = from t in context.Transactions
group t.Create_Date_Time by t.Participation_Id
into t1
select new { ParticipationId = t1.Key, CreateDateTime = t1.Max() };
var cases = from c in context.Cases
group c.Create_Date_Time by c.Participation_Id
into c1
select new { ParticipationId = c1.Key, CreateDateTime = c1.Max() };
var interactions = (from i in context.Interactions
join pp in context.Party_Participation on i.Party_Id equals pp.Party_Id
group i.Last_Update_Date_Time.HasValue ? i.Last_Update_Date_Time : i.Create_Date_Time by
pp.Participation_Id
into i1
select new {ParticipationId = i1.Key, CreateDateTime = i1.Max()}).AsQueryable();
Considering the above code, following will work
transactions.Union(cases);
However following will not work
transactions.Union(interactions);
Because transactions and cases both are returning Linq.IQueryable but the last one is Linq.ParallelQuery due to it join with an another table.
I need this functionality basically to make Union. interactions.Union(transactions) or transactions.Union(interactions) one with other.
The anonymous type of transactions and cases is the same. The anonymous type of interactions is different!
So the solution is to select in a way that makes the anonymous types the same. So either create your own type or convert the select product's properties to the same type.
Something like this should produce the same anonymous type for all the selects:
select new { ParticipationId = (int)c1.Key, CreateDateTime = (DateTime)c1.Max() }
My answer to this question may be incorrect however I raised up this question primarly for the following problem.
LINQ to Entities Union is throwing an error.
I found a fantastic reply from diceguyd30 and it was solved my problem. Hence I am closing this question in response to my previous question's answer.
interactions.Union(transactions.AsEnumerable());
that should work since the first parameter is IQueryable and the second is IEnumerable
Queryable.Union<TSource> Method (IQueryable<TSource>, IEnumerable<TSource>)
Related
Suppose I have a list of {City, State}. It originally came from the database, and I have LocationID, but by now I loaded it into memory. Suppose I also have a table of fast food restaurants that has City and State as part of the record. I need to get a list of establishments that match city and state.
NOTE: I try to describe a simplified scenario; my business domain is completely different.
I came up with the following LINQ solution:
var establishments = from r in restaurants
from l in locations
where l.LocationId == id &&
l.City == r.City &&
l.State == r.State
select r
and I feel there must be something better. For starters, I already have City/State in memory - so to go back to the database only to have a join seems very inefficient. I am looking for some way to say {r.City, r.State} match Any(MyList) where MyList is my collection of City/State.
UPDATE
I tried to update based on suggestion below:
List<CityState> myCityStates = ...;
var establishments =
from r in restaurants
join l in myCityStates
on new { r.City, r.State } equals new { l.City, l.State } into gls
select r;
and I got the following compile error:
Error CS1941 The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.
UPDATE 2
Compiler didn't like anonymous class in the join. I made it explicit and it stopped complaining. I'll see if it actually works in the morning...
It seems to me that you need this:
var establishments =
from r in restaurants
join l in locations.Where(x => x.LocationId == id)
on new { r.City, r.State } equals new { l.City, l.State } into gls
select r;
Well, there isn't a lot more that you can do, as long as you rely on a table lookup, the only thing you can do to speed up things is to put an index on City and State.
The linq statement has to translate into a valid SQL Statement, where "Any" would translate to something like :
SELECT * FROM Restaurants where City in ('...all cities')
I dont know if other ORM's give better performance for these types of scenarios that EF, but it might be worth investigating. EF has never had a rumor for being fast on reads.
Edit: You can also do this:
List<string> names = new List { "John", "Max", "Pete" };
bool has = customers.Any(cus => names.Contains(cus.FirstName));
this will produce the necessary IN('value1', 'value2' ...) functionality that you were looking for
I have a web api project. In database I have two tables of comments and pictures. I want to use join to merge these two tables in such a way that every picture should have all the comments related to it. Both tables have picture id. Which join should I use? I need to use linq. Can someone tell me the linq query I should use?
I have tried cross join, in this way
var combo = from p in db.picturedetails
from c in db.comments
select new CommentAndPictureDetails
{
IdUser = p.iduser,
IdPictures = p.idpictures,
Likes = p.likes,
NudityLevel = p.nuditylevel,
PicTitle = p.picTitle,
PicTime = p.pictime,
FakesLevel = p.fakeslevel,
Comment1 c.comment1,
CTime = c.ctime,
IdComments = c.idcomments,
SpamLevel = c.spamlevel,
TargetPictureId = c.targetpictureid
};
But I am getting all the pictures with all the comments so a very big json. So which join should i use?
What you're looking for a group join:
var query = from p in db.picturedetails
join c in db.comments
on p.PictureId equals c.PictureId into comments
select new
{
ID = p.PictureId,
Comments = comments,
//...
};
My understanding of LINQ is limited at best but I will try to answer what I assume you are asking.
As far as my understanding of your question goes you are wanting the following to work :
Table1:
PictureID
PictureName
Table2:
PictureID
Comments
And the result to have 1 picture with multiple comments. Is this a correct assumption?
If so I do not believe that is possible with 1 single query as the query will return a picture for every comment, the best way would be to find the 1 picture object, then find the multiple comment objects seperately and return them in some fashion to make it appear as one object.
My Code is :
var currency = (from ac in db.shop
join cur in db.books
on ac.CODE equals cur.CODE.ToString() //here is the Error
// because "ac.code is type strig" & "cur.code is type long
where ac.ID == merchantId
select new Currency()
{
ShopCode = ac.CODE,
PosCode = ac.POSCODE,
}).ToList();
I found that .ToString(), SqlFunctions.StringConvert(long) are not working in the join query conditions but working in 'select' area in the query.
However Devart.Data.Oracle.Entity.OracleFunctions.ToChar((long)cur.CODE) is working fine. Since I am using entity framework it shouldn't have problems with particular DB types (i.e. oracle or sql server). It should work even I change from oracle to sql in future.
Please give me a solution for this.
Did you try casting on this.
Try : ac.CODE equals (string)cur.CODE
You can create a VIEW Currency on the database and perform the query on the view.
Here is the list of supported method for Linq to Entities, if conversion is not supported you can not execute it.
http://msdn.microsoft.com/en-us/library/bb738681.aspx
The problem is, that EF is trying to convert whole your expression into T-SQL query.
So it will look similar to this:
select ac.CODE, cur.CODE from shop ac
inner join books cur on ac.CODE = cur.CODE
Here is your problem. CODE fields have diffent types and server can't join on them.
In T-SQL you can use CAST, but since EF don't support such operation you can't do anything.
And afterall, why do you store those codes in string? If you have such a query, then in most cases there is some problem with your DB schema.
I would suggest you to look at the schema and refactor it, so CODE is always of type long. Then everything will work.
If you still really want to use different types for you columns. You can look at this question, to see how to execute CAST Convert String to Int in EF 4.0
this should solve your problem:
var currency = (from ac in db.shop
join cur in db.books
let codestr = cur.CODE.ToString()
on ac.CODE equals codestr
where ac.ID == merchantId
select new Currency()
{
ShopCode = ac.CODE,
PosCode = ac.POSCODE,
}).ToList();
I'm using NHibernate 2.1.2.400, and I'm having an issue with a an ISQLQuery query.
The reason why I use an ISQLQuery here, is that this query uses a table for which I have no entity mapped in NHibernate.
The query looks like this:
ISQLQuery query = session.CreateSQLQuery (
"select p.*, price.* " +
"from prestation p left outer join prestationprice price on p.PrestationId = price.PrestationId " +
"where p.Id IN ( select id from prestationregistry where ...");
'Prestationregistry' is the table that is not known by NHibernate (unmapped, so therefore the native SQL Query).
my code continues like this:
query.AddEntity ("p", typeof(Prestation));
query.AddJoin ("price", typeof(PrestationPrice));
query.SetResultTransformer (Transformers.DistinctRootEntity);
var result = query.List();
So far so good.
I expect that I'm given a list of 'Prestation' instances as a result of this query, since I declared 'Prestation' as being the root-object that has to be returned by the AddEntity method.
I also expect that the PrestationPrices for each Prestation are eagerly loaded by this query (hence the AddJoin method).
To my surprise, the List() method returns a collection of PrestationPrice instances instead of Prestation instances.
How come ? Am I doing something wrong ? And if so, could you be so kind to tell me what I'm doing wrong ?
Edit: Additional Info:
When I debug, and put a watch on the 'query' instance, I can see that the queryReturns member of the query contains 2 items:
- one NativeSqlQueryRootReturn instance who'se ReturnEntityName is 'Prestation'
- one NativeSqlQueryJoinReturn
When I do not specify the 'DistinctRootEntity' result transformer, the query returns instances of 'Prestation' instead of PrestationPrice. However, it contains multiple copies of the same instance.
I'm not sure this is the real cause of your problem, but you must enclose SQL aliases in braces, e.g.
select {p.*}, {price.*}
from prestation p
left outer join prestationprice price on p.PrestationId = price.PrestationId
where p.Id IN ( select id from prestationregistry where ...
Try specifying the type to be returned in the List method:
var result = query.List<Prestation>();
I've solved the problem in a slightly different way.
I didn't know that you could use an SQL expression as an ICriteria-criterion (thx to the NH-Users google-group), so I did it like this:
ICriteria crit = session.CreateCriteria (typeof(Prestation), "p");
crit.SetFetchMode ("p.Prices", FetchMode.Eager);
crit.Add (Expression.Sql ("{alias}.PrestationId = ( SELECT id FROM sometable WHERE ... "));
crit.SetResultTransformer (Transformers.DistinctRootEntity);
var result = crit.List<Prestation>();
Anyway, the question remains if the behaviour that I've got using the ISQLQuery is expected, or a bug ...
The NHUsers thread that I've started as well
var cityList = from country in
doc.Element("result")
.Element("cities")
.Descendants("city")
select new {
Name = country.Element("name").Value,
Code = country.Element("code").Value,
CountryCode = int.Parse(country
.Element("countrycode")
.Value)
};
foreach(var citee in cityList)
{
City city = new City();
city.CountryID = from cnt in db.Countries
where cnt.DOTWInternalID == citee.CountryCode
select cnt.ID;
}
I'm getting an error on the second query as seen in the title of this post. I tried converting to int to nullable int but nothing worked. Help me, guys.
Thanks
it will return an iQueryable, you will need to do something like using the First
cit.CountryID = db.Countries.First(a=>a.DOTWInternalID == citee.CountryCode).ID
It has elapsed a long time since the last update to the post but i think it's worth improving the solution.
In my opinion the solutions posted for this particular scenario are not the best way in terms of performace to get the ID you need. A better solution is as follows.
db.Countries.Where(a=>a.DOTWInternalID == citee.CountryCode)
.Select(a => a.ID).FirstOrDefault();
The previous statemants basically runs a SQL query similar to the following one:
SELECT TOP (1) ID
FROM [dbo].[Countries]
WHERE DOTWInternalID = 123
The proposed solutions work but basically do a "SELECT *" to create the entity with all the values and then obtain the ID from the object just created.
You can use Linqpad to actually see the generated SQL and tune up LINQ queries or Lambdas.
Hope it helps to some others that get to this post.
Here is the problem and solution
from cnt in db.Countries where cnt.DOTWInternalID == citee.CountryCode select cnt.ID part. If you omit the ID then it returns a Generic IEnumerable with Country(hoping that you have Country class). So what you have to do is first return the select criteria and select the first row then the ID field. Same like shown below.
cit.CountryID = (from cnt in db.Countries where cnt.DOTWInternalID == citee.CountryCode select cnt).First<Country>().ID;
This will solve your problem.
IQueryable is not a single int - but a query that can represent a collection.
As the error message says, your Linq query returns an System.Linq.IQueryable (for all intents and purposes a collection of ints). If you'd like to get one of them, you can either call First or ElementAt(n) to get the n'th element.
cit.CountryID = db.Countries.First(a=>a.DOTWInternalID == citee.CountryCode).ID