What does this mean - c#

in this piece of code what does C mean:
var Connection =
from C in Sessions
where (C.StartDate >= StartDate && C.StartDate < EndDate && C.User != null)
select new {C.User.UserName,
DG = C.Machine.DesktopGroup.Name};
https://blogsprod.s3.amazonaws.com/blogs/wp-content/uploads/2014/01/users-connected-to-Delivery-group-for-the-day.txt.gzip

Here, C represents each member of the Sessions collection. This is Linq syntax; see here for more.
If you tell us what type of class Sessions is we can help more.

It's roughly equal to this:
foreach (var c in sessions)
{
c.StartDate >= [....]
}

This is a LINQ expression. The "C" is a random letter or word you set at a beginning of the expression.
I think you might need to learn a bit more about LINQ expressions.

Related

How can i use DateTime.AddXXXX functions in a Linq-to-Entities query?

I am trying to use AddMonths in a query
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true && s.SubscriptionDateTime < DateTime.Now.AddMonths(-1)
select s).ToList();
But I recieve an error :
LINQ to Entities does not recognize the method 'System.DateTime
AddMonths(Int32)' method, and this method cannot be translated into a
store expression.
Is there a way I can use this function inside my query?
The simplest fix to this is to work out the time limit once before using LINQ:
DateTime limit = DateTime.Now.AddMonths(-1);
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true &&
s.SubscriptionDateTime < limit)
select s).ToList();
Or more readably IMO:
var items = context.Subscribers
.Where(s => !s.Validated &&
s.ValidationEmailSent &&
s.SubscriptionDateTime < limit)
.ToList();
There's no benefit in using a query expression here, and explicit comparisons with true and false are ugly IMO (unless your properties are of type Nullable<bool> of course).
Jon Skeet has already provided a simple fix, but if you want the DateTime.Now.AddMonths bit to run on the database, try the EntityFunctions.AddMonths method.
This is a more general approach that is especially useful when you cannot replicate the expression cheaply or correctly on the client.
You can change your code to:
DateTime oneMonth = DateTime.Now.AddMonths(-1)
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true && s.SubscriptionDateTime < oneMonth
select s).ToList();
You have to do this because AddMonth is a .NET function that can't be translated into SQL by Linq to Entities. Perform the calculation in your code and then use the resulting datetime will work.

Convert this code to LINQ?

Sorry, Im just learning LINQ and am relatively new at it.
Is it possible to convert the following into LINQ?
foreach (DataRow gradeCount in GraceTable.Rows)
{
if (Convert.ToDecimal(obtMarksRow["Percentage"]) >=
(Convert.ToDecimal(gradeCount["EXG_MARKS_ABOVE"])) &&
(Convert.ToDecimal(obtMarksRow["Percentage"]) <=
Convert.ToDecimal(gradeCount["EXG_MARKS_BELOW"])))
{
string Grade = Convert.ToString(gradeCount["EXG_GRADE_NAME"]);
}
}
Edit : sorry i missed for each loop in ma query and obtMarksRow comes from one more loop which is outside this
I wrote the query like this
var gradeValue = from DataRow gradeRow in GraceTable.Rows
let marksAbove = gradeRow.Field<decimal>("EXG_MARKS_ABOVE")
let marksBelow = gradeRow.Field<decimal>("EXG_MARKS_BELOW")
where obtMarksRow.Field<decimal>("Percentage") >= marksAbove && obtMarksRow.Field<decimal>("Percentage") <= marksBelow
select gradeRow.Field<string>("EXG_GRADE_NAME");
but i am getting the value (gradeValue.ToString() ) as "System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.Data.DataRow,System.String]"
Whats wrong ?
No, it isn't possible. As the commenters point out, LINQ is for querying collections of things. You don't appear to have a collection here: just an if statement and an assignment.
Furthermore, be careful about trying to convert things to LINQ unnecessarily. As you start to understand LINQ better, you'll find yourself naturally using it for a variety of purposes. But starting off with the assumption that code will be better with LINQ is probably a fallacy.
Edit
As mentioned earlier, LINQ is about querying a collection for a set of results. If you only want one result, you can use Single, First, SingleOrDefault, or FirstOrDefault to get it out of the resulting collection.
var gradeValues = from DataRow gradeRow in GraceTable.Rows
let marksAbove = gradeRow.Field<decimal>("EXG_MARKS_ABOVE")
let marksBelow = gradeRow.Field<decimal>("EXG_MARKS_BELOW")
where obtMarksRow.Field<decimal>("Percentage") >= marksAbove && obtMarksRow.Field<decimal>("Percentage") <= marksBelow
select gradeRow.Field<string>("EXG_GRADE_NAME");
var firstGradeValue = gradeValues.First(); // will throw exception if there were no matches.
Console.WriteLine(firstGradeValue);
Try the following:
var grades = from r in GraceTables.Rows
where obtMarksRow.Field<decimal>("Percentage") >=
r.Field<decimal>("EXG_MARKS_ABOVE") &&
obtMarksRow.Field<decimal>("Percentage") <=
r.Field<decimal>("EXG_MARKS_BELOW")
select r.Field<string>("EXG_GRADE_NAME");
You shouldn't use Linq per se but you should use the DatasetExtensions, brought in alongside linq, to get your columns from the DataRow in a type safe way without the need to convert them, i.e.
if (obtMarksRow.Field<decimal>("Percentage") >= (Convert.ToDecimal(gradeCount["EXG_MARKS_ABOVE"])) && etc...

How do I convert this expression to LINQ?

Is it possible to convert this expression to LINQ?
TermsOfPayment termsOfPayment = null;
foreach (CustomerGroup group in _customer.CustomerGroups)
if (termsOfPayment == null) termsOfPayment = group.TermsOfPayment;
else if (group.TermsOfPayment != null)
if (group.TermsOfPayment.InvoiceDueDays < termsOfPayment.InvoiceDueDays)
termsOfPayment = group.TermsOfPayment;
It might seem like a stupid question since the expression above solves the question, but I use some LINQ expressions and am eager to lern more - hence the reason for this post.
Basically I just want to select the TermsOfPayment object with the minimum InvoiceDueDays (integer) value from the groups the customer is a part of.
termsOfPayment = (
from g in _customer.CustomerGroups
where g.TermsOfPayment != null
orderby g.TermsOfPayment.InvoiceDueDays
select g.TermsOfPayment
).FirstOrDefault();
var termsOfPayment =
_customer.CustomerGroups.OrderBy(cg=>cg.TermsOfPayment.InvoiceDueDays)
.First().Select(cg=>cg.TermsOfPayment);
Why not use aggregate, speed is better too:
var termsOfPayment =
_customer.CustomerGroups.Aggregate((a, n) => n.TermsOfPayment.InvoiceDueDays < a.TermsOfPayment.InvoiceDueDays ? n : a).TermsOfPayment;

Dynamic WHERE clause in LINQ

What is the best way to assemble a dynamic WHERE clause to a LINQ statement?
I have several dozen checkboxes on a form and am passing them back as: Dictionary<string, List<string>> (Dictionary<fieldName,List<values>>) to my LINQ query.
public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
var q = from c in db.ProductDetail
where c.ProductGroupName == productGroupName && c.ProductTypeName == productTypeName
// insert dynamic filter here
orderby c.ProductTypeName
select c;
return q;
}
(source: scottgu.com)
You need something like this? Use the Linq Dynamic Query Library (download includes examples).
Check out ScottGu's blog for more examples.
I have similar scenario where I need to add filters based on the user input and I chain the where clause.
Here is the sample code.
var votes = db.Votes.Where(r => r.SurveyID == surveyId);
if (fromDate != null)
{
votes = votes.Where(r => r.VoteDate.Value >= fromDate);
}
if (toDate != null)
{
votes = votes.Where(r => r.VoteDate.Value <= toDate);
}
votes = votes.Take(LimitRows).OrderByDescending(r => r.VoteDate);
You can also use the PredicateBuilder from LinqKit to chain multiple typesafe lambda expressions using Or or And.
http://www.albahari.com/nutshell/predicatebuilder.aspx
A simple Approach can be if your Columns are of Simple Type like String
public static IEnumerable<MyObject> WhereQuery(IEnumerable<MyObject> source, string columnName, string propertyValue)
{
return source.Where(m => { return m.GetType().GetProperty(columnName).GetValue(m, null).ToString().StartsWith(propertyValue); });
}
It seems much simpler and simpler to use the ternary operator to decide dynamically if a condition is included
List productList = new List();
productList =
db.ProductDetail.Where(p => p.ProductDetailID > 0 //Example prop
&& (String.IsNullOrEmpty(iproductGroupName) ? (true):(p.iproductGroupName.Equals(iproductGroupName)) ) //use ternary operator to make the condition dynamic
&& (ID == 0 ? (true) : (p.ID == IDParam))
).ToList();
I came up with a solution that even I can understand... by using the 'Contains' method you can chain as many WHERE's as you like. If the WHERE is an empty string, it's ignored (or evaluated as a select all). Here is my example of joining 2 tables in LINQ, applying multiple where clauses and populating a model class to be returned to the view. (this is a select all).
public ActionResult Index()
{
string AssetGroupCode = "";
string StatusCode = "";
string SearchString = "";
var mdl = from a in _db.Assets
join t in _db.Tags on a.ASSETID equals t.ASSETID
where a.ASSETGROUPCODE.Contains(AssetGroupCode)
&& a.STATUSCODE.Contains(StatusCode)
&& (
a.PO.Contains(SearchString)
|| a.MODEL.Contains(SearchString)
|| a.USERNAME.Contains(SearchString)
|| a.LOCATION.Contains(SearchString)
|| t.TAGNUMBER.Contains(SearchString)
|| t.SERIALNUMBER.Contains(SearchString)
)
select new AssetListView
{
AssetId = a.ASSETID,
TagId = t.TAGID,
PO = a.PO,
Model = a.MODEL,
UserName = a.USERNAME,
Location = a.LOCATION,
Tag = t.TAGNUMBER,
SerialNum = t.SERIALNUMBER
};
return View(mdl);
}
Just to share my idea for this case.
Another approach by solution is:
public IOrderedQueryable GetProductList(string productGroupName, string productTypeName, Dictionary> filterDictionary)
{
return db.ProductDetail
.where
(
p =>
(
(String.IsNullOrEmpty(productGroupName) || c.ProductGroupName.Contains(productGroupName))
&& (String.IsNullOrEmpty(productTypeName) || c.ProductTypeName.Contains(productTypeName))
// Apply similar logic to filterDictionary parameter here !!!
)
);
}
This approach is very flexible and allow with any parameter to be nullable.
You could use the Any() extension method. The following seems to work for me.
XStreamingElement root = new XStreamingElement("Results",
from el in StreamProductItem(file)
where fieldsToSearch.Any(s => el.Element(s) != null && el.Element(s).Value.Contains(searchTerm))
select fieldsToReturn.Select(r => (r == "product") ? el : el.Element(r))
);
Console.WriteLine(root.ToString());
Where 'fieldsToSearch' and 'fieldsToReturn' are both List objects.
This is the solution I came up with if anyone is interested.
https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/
First we identify the single element type we need to use ( Of TRow As DataRow) and then identify the “source” we are using and tie the identifier to that source ((source As TypedTableBase(Of TRow)). Then we must specify the predicate, or the WHERE clause that is going to be passed (predicate As Func(Of TRow, Boolean)) which will either be returned as true or false. Then we identify how we want the returned information ordered (OrderByField As String). Our function will then return a EnumerableRowCollection(Of TRow), our collection of datarows that have met the conditions of our predicate(EnumerableRowCollection(Of TRow)). This is a basic example. Of course you must make sure your order field doesn’t contain nulls, or have handled that situation properly and make sure your column names (if you are using a strongly typed datasource never mind this, it will rename the columns for you) are standard.
System.Linq.Dynamic might help you build LINQ expressions at runtime.
The dynamic query library relies on a simple expression language for formulating expressions and queries in strings.
It provides you with string-based extension methods that you can pass any string expression into instead of using language operators or type-safe lambda extension methods.
It is simple and easy to use and is particularly useful in scenarios where queries are entirely dynamic, and you want to provide an end-user UI to help build them.
Source: Overview in Dynamic LINQ
The library lets you create LINQ expressions from plain strings, therefore, giving you the possibility to dynamically build a LINQ expression concatenating strings as you require.
Here's an example of what can be achieved:
var resultDynamic = context.Customers
.Where("City == #0 and Age > #1", "Paris", 50)
.ToList();

C#: Is it possible to declare a local variable in an anonymous method?

Is is possible to have a local variable in an anonymous c# methods, i.e. in the following code I would like to perform the count only once.
IQueryable<Enquiry> linq = db.Enquiries;
if(...) linq = linq.Where(...);
if(...) linq = linq.Where(e =>
(x <= (from p in db.Orders where p.EnquiryId == e.Id select p).Count() &&
(from p in db.Orders where p.EnquiryId == e.Id select p).Count() <= y));
if(...) linq = linq.Where(...);
var result = (from e in linq select e);
Is there a "let" for anonymous functions?
Update:
Note that I'm adding several Where clauses after this statement so I can't close with a select.
/Niels
Yes, why not?! After all it's a function, just anonymous!
Example:
x => { int y = x + 1; return x + y; }
Or alternatively:
delegate(int x) {
int y = x + 1;
return x + y;
}
So your code can be written as:
... = linq.Where(e => {
var count = (from p in db.Orders where p.EnquiryId == e.Id select p).Count();
return x <= count && count <= y;
});
UPDATE: To clarify things about the comment, it's important to know the difference between anonymous methods and lambda expressions. An anonymous method is just like a normal method, without an explicit name. When you compile it, the compiler generates a normal method with a weird name for you instead, so it will not have any special limitations. However, one representation of an anonymous method is a lambda expression. Lambda expressions can be interpreted in a couple different ways. The first is a delegate. In that way, they are equal to an anonymous method. The second is an expression tree. This way is normally used by LINQ to SQL and some other LINQ providers. They don't execute your expression directly by any means. They parse it as an expression tree and use the tree as input data to generate the equivalent SQL statement to be run on the server. It's not executed like a method and it's not considered an anonymous method. In that case, you can't define a local variable as it's not possible to parse the lambda as an expression tree.
Yes, you can do exactly what you want, in Linq to objects and Linq to SQL.
There is a let in Linq, allowing you to give a name to an intermediate result in the middle of your query, just as you want to. Based on your example:
... = from e in linq
let count = (from p in db.Orders where p.EnquiryId == e.Id select p).Count()
where (x <= count) && (count <= y)
select e;
By the way, I think there was something syntactically erroneous about your original example, which is easier to spot when the count is just a name:
where (x <= count) && /* <= */ (count <= y);
If you're using Linq to SQL, you won't be able to use Mehrdad Afshari's answer. Your LINQ expressions need to be Expression Trees, and those don't support the anonymous delegate syntax.
Neither will you be able to create your delegate elsewhere and call it from inside the lambda - Linq to SQL only allows certain operations to be performed in the body of the query, and calling a delegate isn't one of them.
Your best bet, assuming you're using Linq to SQL (as it appears given your example), is to bring down the count in one query, then capture the count variable in the query that requires the count.
The Where method takes a Func so what you're passing in there in the second part ins't actually a method, but just a bool expression. My suggestion would be to have an actual method that returns a bool, that takes in the paremeters you need, and in your call to the Where method you just do something like this Where(p=> MyMethod(p,...))
I've run into a similar problem. The solution is to create a custom expression tree generating method.
I asked my question on MSDN-forums. Please see the question and answer here: Reusing Where expressions.
This may give you an idea on how to proceed, but I must admit that custom expression trees are not for the faint-hearted ;-)
With a little background in Scheme you would know that 'let' is just syntax sugar for defining a lambda and invoking it.
So with that knowledge, lets see how it can be done.
(count => x <= count && count <= y)
((from p in db.Orders
where p.EnquiryId == e.Id
select p).Count())
As a bonus, it looks like Scheme too :)
Disclaimer: I did not test this snippet, but there is no reason it should not work. Personally, I would just use the 'let' construct provided in LINQ.
Update:
It does not work... :(

Categories

Resources