I know this question has been asked many times and I know that the Distinct call destroys the previous order so I must use the OrderBy afterwards, but in this case I must be doing something else wrong.
int[] resources = (from a in context.Beamline_Requests
join b in context.Technique_Requests on a.Technique_Request_ID equals b.ID
where b.Beamtime_Request_ID == id
select a.Beamline_ID).Distinct().OrderBy(a => a.ID).ToArray();
I receive the:
Cannot convert lambda expression to type 'System.Linq.Expressions.LambdaExpression' because it is not a delegate type
error message on the OrderBy. It also says:
'int' does not contain a definition for 'ID' and no extension method 'ID' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
So apparently the 'a' is no longer part of the context.
I have done similar things successfully but in those cases I am projecting the Linq into a ViewModel so in this case it must have something to do with attempting to just make it an array.
You are only selecting field Beamline_ID and later you are trying to OrderBy ID, Your intermediate result from select doesn't have field ID it is just a projection of int numbers. As #GrantWinney suggested you can do OrderBy(a=> a) like:
int[] resources = (from a in context.Beamline_Requests
join b in context.Technique_Requests on a.Technique_Request_ID equals b.ID
where b.Beamtime_Request_ID == id
select a.Beamline_ID).Distinct().OrderBy(a => a).ToArray();
For the comment:
My issue though is that I actually do need to order by the ID, not the
Beamline_ID even though I only need the Beamline_ID in the array.
int[] resources = (from a in context.Beamline_Requests
join b in context.Technique_Requests on a.Technique_Request_ID equals b.ID
where b.Beamtime_Request_ID == id
select new
{
Beamline_ID = a.Beamline_ID,
ID = b.ID
})
.OrderBy(a => a.ID)
.Select(r=> r.Beamline_ID)
.Distinct()
.ToArray();
Or in a simpler version you can achieve:
int[] resources = (from a in context.Beamline_Requests
join b in context.Technique_Requests on a.Technique_Request_ID equals b.ID
where b.Beamtime_Request_ID == id
orderby b.ID
select a.Beamline_ID)
.Distinct()
.ToArray();
Related
In the Where clause of a Linq statement, like this,
var myClasses = (from b in db.MyRecords
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
where (b.Active == 1)
select new { b });
The expression b.Active==1 works fine. But if I do this,
Expression<Func<MyRecords, bool>> filter = my => my.Active == 1;
[Update: Because of Hans' answer I have kept this as the original, but in reality, I mistyped here. The Expression is actually using the underlying type, not the EF generated plural like the query Linq. I actually have this,
Expression<Func<MyRecord, bool>> filter = my => my.Active == 1;
]
And try this,
var myClasses = (from b in db.MyRecords
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
where (filter)
select new { b });
The compiler complains,
Cannot convert query expression to intended delegate type because some
of the return types in the block are not implicitly convertible to the
delegate return type
I have seen lots of SO question with this, but I do not understand why it will not work. I am misunderstanding fundamental, so I'm not really asking anyone to write the code. I want to know what Linq wants so I have a better understanding of Linq, not just making something work. This works, for example,
var myClasses = (from b in db.MyRecords.Where(filter)
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
select new { b });
I want to know why it works there and not in the Where after the joins. If I do the Where at the end of the joins, the compiler is still aware of the MyRecords fields, including Active.
I think this is what I'm after for a proper description, as it seems to fit my probably pretty well.
http://www.albahari.com/nutshell/linqkit.aspx
Your filter is just of wrong type to be applied in the first example. The blue linq syntax does a lot of magic for you to make this query easy to read. What actually happens under the hood is creation of some anonymous types that contain references to your items. Note that in that where clause you can use p and cse variables as well. And when you factor that to your expression you might figure it to be like this Expression<Func<Tuple<MyRecords, People, Courses>> in reality it will not be a tuple but some anonymous type.
When you ask resharper to convert blue syntax to method chain it generates it like this:
(db.MyRecords.Join(
db.People,
b => b.PersonId,
p => p.PersonId,
(b, p) => new {b, p})
.Join(
db.Courses,
t => t.b.CourseId,
cse => cse.CourseId,
(t, cse) => new {t, cse})
.Where(t => (t.t.b.Active == 1))
.Select(t => new {t.t.b}));
And actually you cannot use the filter variable in the blue syntax like you did:
... join cse in db.Courses on b.CourseId equals cse.CourseId
where (filter)
You would have to switch to method call:
(from b in db.MyRecords
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
select b)
.Where(filter)
now just because we trimmed the inner query to just b you can apply you filter.
This question already has answers here:
Error: Only primitive types or enumeration types are supported in this context EF
(2 answers)
Closed 5 years ago.
Trying to do this, different database:
var IDs = (from a in db1.Table1
join b in db1.Table2 on a.Id equals b.Id
orderby a.Status
where b.Id == 1 && a.Status == "new"
select new Company { a.Id }).ToList();
var query = (from c in db2.Company
join a in IDs on c.Id equals a.Id
select new Company { Id = a.Id, CompanyId = c.CompanyId }).OrderByDescending(z => z.CompanyId).ToList();
I got this:
Additional information: Unable to create a constant value of type 'M.Models.Company'. Only primitive types or enumeration types are supported in this context.
I think it is because of the ToList() at the second query.
The most likely issue here is that the 2nd query has no good way of representing that as a join. I suspect your best option would be to switch to Contains:
var IDs = (from a in db1.Table1
join b in db1.Table2 on a.Id equals b.Id
where b.Id == 1 && a.Status == "new"
select a.Id).Distinct().ToList();
var query = (from c in db2.Company
where IDs.Contains(c.Id)
select new { Id = a.Id, CompanyId = c.CompanyId }
).OrderByDescending(z => z.CompanyId).ToList();
This isn't ideal, and it will struggle for large lists, but it is at least a simpler pattern to represent into a parameterized query.
I have foreign table with one to many relation. I write linq query as left join equivalent and implement group by relevant id field.
from p in db.personal join pn in
(from t in db.phoneNumbers
group t by t.personID into g
select new { id = g.Key,
number = g.Select(t => t.number),
prefix = g.Select(t => t.prefix)
}).AsEnumerable()
on p.ID equals pn.id
into lPN from lpn in lPN.DefaultIfEmpty()
//join wsd in db.basicOperations on p.ID equals wsd.personID
where p.ID == id.Value
select new partialPersonDetailsViewModel()
{
id = id.Value,
genderType = p.genderType,
sPhoneNumbers="(" +lpn.prefix+") "+lpn.number
}).FirstOrDefault();
But at sPhoneNumbers="(" +lpn.prefix+") "+lpn.number this place VS notify me about error:
Error 1 Operator '+' cannot be applied to operands of type 'System.Collections.Generic.IEnumerable' and 'System.Collections.Generic.IEnumerable'
Please help me pass this error and solve problem.
Both of lpn.prefix and lpn.number are evaluated as g.Select(...), so in fact they are IEnumerable<T> (exactly as error message declares it).
Evaluating them as g.Select(...).FirstOrDefault() should help you since it will extract value of type T from IEnumerable<T>.
Update:
In your case, when lpn.prefix and lpn.number are actually lists of values and you need to concatenate these lists - you can use something like:
sPhoneNumbers = String.Join("; ",
lpn.prefix.Select((p, i) =>
String.Format("({0}){1}",
p,
lpn.numbers.Skip(i).Take(1).FirstOrDefault())));
Or you can use Enumerable.Zip method, as it was suggested in comments by #Chris:
sPhoneNumbers = String.Join("; ",
lpn.prefix.Zip(lpn.numbers,
(s, s1) => string.Format("({0}){1}", s, s1)));
I want to use Skip and Take for my paging, but I also want to use orderby
Without the Skip and Take, with LinqPad I can do the following and this works with orderby
var query = from m in Orders
orderby m.ID descending
select m;
query.Dump();
However, if I keep the orderby in, then this fails
query = query.Skip(1 + 10).Take(10);
query.Dump();
I remove the orderby and it works, but I want the orderby ....
var query = from m in Orders
select m;
query = query.Skip(1 + 10).Take(10);
query.Dump();
Error occurs, because you use var and compiler infer query type as IOrderedEnumerable<T> after your first query, and you're trying to assign IEnumerable<T> to it with Skip/Take calls:
Cannot implicitly convert type
'System.Collections.Generic.IEnumerable<Order>' to
'System.Linq.IOrderedEnumerable<Order>'. An explicit conversion exists
(are you missing a cast?)
If you type query as IEnumerable<T> at the beginning everything will work just fine
IEnumerable<Order> query = from m in Orders
orderby m.ID descending
select m;
query = query.Skip(10).Take(10);
The selected answer is correct, however If you are not binding to a model with of Type Order, then this would work
MarcinJuraszek is correct.
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<Order>' to 'System.Linq.IOrderedEnumerable<Order>'. An explicit conversion exists (are you missing a cast?)
You will get that error the way you are doing it
HOWEVER to NOT have to use IEnumerable<Order> ...
var query = (from m in Orders
orderby m.ID descending
select m).Skip(10).Take(10);
query.Dump();
I had the same issue in LINQPAD when I knew that I wanted to skip over the first record
So for me :
var comments = (from c in ESO_tblComments
.Where(d => d.TblTipsId == 10312)
orderby c.Id ascending
select c).Skip(1);
for more. if you use it or not you can sort your query without ascending or descending style. you can use below code.
var comments = (from c in ESO_tblComments
.Where(d => d.TblTipsId == 10312)
select c).OrderBy(xx=>1==1).Skip(1);
var Query2 = from x in CoreDatabase.Set<tblPerson>()
.Include(a => a.tblApplicationInterface.Select(b => b.tblApplicationName)
.Where(c => c.AppplicationName == "MshHumanResources"))
select x;
I get The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
I am simply trying to write
Here something that works:
Select *
From tblPerson a INNER JOIN tblApplicationInterface b
on a.id = b.id
INNER Join tblApplicationName c
ON b.fkid=c.id
Where b.ApplicationName like 'MshHumanResources'
That's not how Include works. You want to use join instead:
var Query2 = from a in CoreDatabase.Set<tblPerson>()
join b in CoreDatabase.Set<tblApplicationInterface>() on a.id equlas b.id
join c in CoreDatabase.Set<tblApplicationName>() on b.fkid equals c.id
where c.AppplicationName == "MshHumanResources"
select a;
This is just selecting the columns from A - if you want to select columns from the other tables either create a class to combine the fields you need or use an anonymous type.
Directly, you could say
var people = CoreDatabase.Set<tblPerson>().Where( p =>
p.tblApplicationInterface.tblApplicationName.ApplicationName == "MshHumanResources" );
If I understand your navigation properties correctly. This would select people who's app interface's app name was MshHumanResources.
Try this:
var Query2 = CoreDatabase.Set<tblPerson>
.Include("tblApplicationInterface")
.Include("tblApplicationInterface.tblApplicationName")
.Where(x => x.ApplicationName == "MshHumanResources");