Lambda Expression for LINQ Select Items - linq

I have this code
var list = _db.Projects.Where(item => item.Loc =="IN").Select(p => new {id=p.Id, title=p.Title,pc=p.PostalCode });
Project table having lot of columns, i need to query required columns dynamically and load from database, not all columns along with data.
Questions:
how to write lambda expressions for linq select ?
How to reduce data reads on database by selecting specific cols, entity framework ?

Look at the expression the C# compiler generated and try to replicate what it does:
Expression<Func<Project, object>> lambda =
(Project p) => (object)new {id=p.Id, title=p.Title,pc=p.PostalCode };
I hope this code compiles. If not, you'll surely be able to fix it. Afterwards, look at the contents of the lambda variable.
Note, that the cast to object is only there to make this compile. You don't need/want that is production.

Related

Select distinct value from a list in linq to entity

There is a table, it is a poco entity generated by entity framework.
class Log
{
int DoneByEmpId;
string DoneByEmpName
}
I am retrieving a list from the data base. I want distinct values based on donebyempid and order by those values empname.
I have tried lot of ways to do it but it is not working
var lstLogUsers = (context.Logs.GroupBy(logList => logList.DoneByEmpId).Select(item => item.First())).ToList(); // it gives error
this one get all the user.
var lstLogUsers = context.Logs.ToList().OrderBy(logList => logList.DoneByEmpName).Distinct();
Can any one suggest how to achieve this.
Can I just point out that you probably have a problem with your data model here? I would imagine you should just have DoneByEmpId here, and a separate table Employee which has EmpId and Name.
I think this is why you are needing to use Distinct/GroupBy (which doesn't really work for this scenario, as you are finding).
I'm not near a compiler, so i can't test it, but...
Use the other version of Distinct(), the one that takes an IEqualityComparer<TSource> argument, and then use OrderBy().
See here for example.

Linq To Entities 'Only primitive types or enumeration types are supported' Error

I am using LinqPad to test my query. This query works when the LInqPad connection is to my database (LInq to SQL) but it does not work when I change the connection to use my Entity Framework 5 Model.dll. (Linq to Entity). This is in C#.
I have two tables called Plan and PlanDetails. Relationship is one Plan to many PlanDetails.
var q = from pd in PlanDetails
select new {
pd.PlanDetailID,
ThePlanName = (from p in this.Plans
where p.PlanID == pd.PlanID
select p.PlanName)
};
var results = q.ToList();
q.Dump(); //This is a linqpad method to output the result.
I get this error "NotSupportedException: Unable to create a constant value of type 'Domain.Data.Plan'. Only primitive types or enumeration types are supported in this context." Any ideas why this only works with Linq to SQL?
basically it means you are using some complex datatype inside the query for comparison.
in your case i suspect from p in this.Plans where p.PlanID == pd.PlanID is the culprit.
And it depends on DataProvider. It might work for Sql Data Provider, but not for SqlCE data Provider and so on.
what you should do is to convert your this.Plans collection into a primitive type collection containing only the Ids i.e.
var integers = PlanDetails.Plans.Select(s=>s.Id).ToList();
and then use this list inside.
var q = from pd in PlanDetails
select new {
pd.PlanDetailID,
ThePlanName = (from p in integers
where p == pd.PlanID
select pd.PlanName)
};
I got this error when i was trying to null check for a navigational property in the entity framework expression
I resolved it by not using the not null check in the expression and just using Any() function only.
protected Expression<Func<Entities.Employee, bool>> BriefShouldAppearInSearchResults(
IQueryable<Entities.Employee> briefs, string username)
{
var trimmedUsername = NameHelper.GetFormattedName(username);
Expression<Func<Entities.Employee, bool>> filterExpression = cse =>
cse.Employee.Cars.All(c =>
c.Employee.Cars!=null && <--Removing this line resolved my issue
c.Employee.Cars.Any(cur => cur.CarMake =="Benz")));
return filterExpression;
}
Hope this helps someone!
This is a Linqpad bug if you like (or a peculiarity). I found similar behaviour myself. Like me, you may find that your query works with an ObjectContext, but not a DbContext. (And it works in Visual Studio).
I think it has to do with Linqpad's inner structure. It adds MergeAs (AppendOnly) to collections and the context is a UserQuery, which probably contains some code that causes this bug.
This is confirmed by the fact that the code does work when you create a new context instance in the Linqpad code and run the query against this instance.
If the relationship already exists.
Why not simply say.
var q = from pd in PlanDetails
select new {
pd.PlanDetailID,
ThePlanName = pd.Plan.PlanName
};
Of course i'm assuming that every PlanDetail will belong to a Plan.
Update
To get better results from LinqPad you could tell it to use your own assembly (which contains your DbContext) instead of the default Datacontext it uses.

Entity Framework LINQ Query using Custom C# Class Method - Once yes, once no - because executing on the client or in SQL?

I have two Entity Framework 4 Linq queries I wrote that make use of a custom class method, one works and one does not:
The custom method is:
public static DateTime GetLastReadToDate(string fbaUsername, Discussion discussion)
{
return (discussion.DiscussionUserReads.Where(dur => dur.User.aspnet_User.UserName == fbaUsername).FirstOrDefault() ?? new DiscussionUserRead { ReadToDate = DateTime.Now.AddYears(-99) }).ReadToDate;
}
The linq query that works calls a from after a from, the equivalent of SelectMany():
from g in oc.Users.Where(u => u.aspnet_User.UserName == fbaUsername).First().Groups
from d in g.Discussions
select new
{
UnReadPostCount = d.Posts.Where(p => p.CreatedDate > DiscussionRepository.GetLastReadToDate(fbaUsername, p.Discussion)).Count()
};
The query that does not work is more like a regular select:
from d in oc.Discussions
where d.Group.Name == "Student"
select new
{
UnReadPostCount = d.Posts.Where(p => p.CreatedDate > DiscussionRepository.GetLastReadToDate(fbaUsername, p.Discussion)).Count(),
};
The error I get is:
LINQ to Entities does not recognize the method 'System.DateTime GetLastReadToDate(System.String, Discussion)' method, and this method cannot be translated into a store expression.
My question is, why am I able to use my custom GetLastReadToDate() method in the first query and not the second? I suppose this has something to do with what gets executed on the db server and what gets executed on the client? These queries seem to use the GetLastReadToDate() method so similarly though, I'm wondering why would work for the first and not the second, and most importantly if there's a way to factor common query syntax like what's in the GetLastReadToDate() method into a separate location to be reused in several different other LINQ queries.
Please note all these queries are sharing the same object context.
I think your better of using a Model Defined Function here.
Define a scalar function in your database which returns a DateTime, pass through whatever you need, map it on your model, then use it in your LINQ query:
from g in oc.Users.Where(u => u.aspnet_User.UserName == fbaUsername).First().Groups
from d in g.Discussions
select new
{
UnReadPostCount = d.Posts.Where(p => p.CreatedDate > myFunkyModelFunction(fbaUsername, p.Discussion)).Count()
};
and most importantly if there's a way to factor common query syntax like what's in the GetLastReadToDate() method into a separate location to be reused in several different places LINQ queries.
A stored procedure would probably be one way to store that 'common query syntax"...EF, at least 4.0, works very nicely with SP's.

DynamicObject LINQ query does't works with custom class!

DynamicObject LINQ query with the List compiles fine:
List<string> list = new List<string>();
var query = (from dynamic d in list where d.FirstName == "John" select d);
With our own custom class that we use for the "usual" LINQ compiler reports the error "An expression tree may not contain a dynamic
operation":
DBclass db = new DBclass();
var query = (from dynamic d in db where d.FirstName == "John" select d);
What shall we add to handle DynamicObject LINQ?
Does DBClass implement IEnumerable? Perhaps there is a method on it you should be calling to return an IEnumerable collection?
You could add a type, against which to write the query.
I believe your problem is, that in the first expression, where you are using the List<>, everything is done in memory using IEnumerable & Link-to-Objects.
Apparently, your DBClass is an IQueryable using Linq-to-SQL. IQueryables use an expression tree to build an SQL statement to send to the database.
In other words, despite looking much alike, the two statements are doing radically different things, one of which is allowed & one which isn't. (Much in the way var y = x * 5; will either succeed or fail depending on if x is an int or a string).
Further, your first example may compile, but as far as I can tell, it will fail when you run it. That's not a particular good benchmark for success.
The only way I see this working is if the query using dynamic is made on IEnumerables using Link-to-Objects. (Load the full table into a List, and then query on the list)

LINQ to DataSet and xml help

I created a strongly-typed dataset in the dataset designer. The DataSet has a Table called FocusOffsetsTable and that table has four colums; SerialNumber, Filter, Wheel and Offset. I use the ReadXml() method of the DataSet class to load the strongly typed data from the xml file into the dataset. That seems to be working just fine.
I am trying to use a LINQ expression to try to get a Single row from this table but I can't seem to get the syntax correct. I want to use the Single() or SingleOrDefault() method to get just one row of data at a time but I am not sure how.
I have tried this FocusOffsets.FocusOffsetsTableRow x = FocusOffsetData.FocusOffsetsTable. but the Single() method is not available here. I also tried this...
FocusOffsets.FocusOffsetsTableRow x = (from offset in FocusOffsetData.FocusOffsetsTable
where offset.SerialNumber == mydevice.SerialNumber
where offset.Wheel == WheelID
where offset.Filter == FilterNum
select offset).Single();
but the Single method is not available here either.
I have done this before with tables in a SQL database before but this is my first time using a dataset from the dataset designer.
Have you added a using statement for System.Linq and included a reference to System.Data.DataSetExtensions. I think (but can't confirm since I'm on my Mac), that you ought to be able to do:
var x = FocusOffsetData.FocusOffsetsTable
.AsEnumerable()
.SingleOrDefault( o => o.SerialNumber == mydevice.SerialNumber
&& o.Wheel = WheelID
&& o.Filter = FilterNum );

Resources