The xml elements are variable depending on some conditional. I need to initialize an instance with a different element, based on the value of some other element.
var result = (from name in names
select new MyName
{
name.First = name.Type = Fracais ? name.PreNom : name.First,
name.Last
}
Any ideas?
What you have is almost right. I had to guess the enums and members as you don't provide the other classes:
var result = from name in names
select new Person()
{
First = name.Type == PersonType.Fracais ? name.PreNom : name.First,
Last = name.Last
};
You can have pretty much any expression, including function calls, in a linq query, so testing values and mutating them on the fly is perfectly acceptable.
How about this? As a pointless alternative.
var result = names.where(name => name.Type == Francais).Select(name =>
name.PreNom, name.Last).Union()
names.where(name => name.Type != Francais).Select(name.First, name.Last);
Related
I have two variables. first variable docList of type www.abc.com.docListResponse. It consists of an array of values with docID[0] = "12345", docID[1] = "34567" docID[2] = "32498"
The second variable is of custom type Documents[] docsColl with values docRefID[0] = "12345", docRefID[1] = "34567", DocRefID[2] = "67890"
The ling operator
var docs = docsColl.ToList().Where(i => i.docRefID== docList .FirstOrDefault().docID.ToString()).ToArray();
I'm expecting it to return two records but its returning 0.
If you need to compose a query using another existing collection, you can generally use the Any() method to accomplish this, which will return any records that match your specific constraint.
var docs = docsColl.Where(d => docList.Any(x => d.docID == x.docRefID));
One caveat with this is that if you are using complex types and your initial collection is not in memory (and is in something like a database), LINQ won't know how to properly handle this, so you typically need to either throw a ToList() call prior to your Where() statement :
var docs = docsColl.ToList()
.Where(d => docList.Any(x => d.docID == x.docRefID));
Or you'll need to ensure that the collection you are using to query through (in this case docList) only consists of primitive types like strings :
// Get your IDs to check against
var docRefIds = docList.Select(d => d.docRefID).ToArray();
var docs = docsColl.Where(d => docRefIds.Any(r => d.docID == r));
Why the code below returns nothing when I try to query an IList type object?
IList<Person> personRecord = new List<Person>
{
new Person{ Name = "Samuel"},
new Person{ Name = "Kenny Sammy"},
new Person{ Name = "Jame Sam Lee"}
};
var names = from b in personRecord
where personRecord.Any(d => d.Name == "Sam")
select b;
return names.ToList();
Don't use Any simply use the condition in Where clause like:
var names = from b in personRecord
where b.Name == "Sam"
select b;
or with a method syntax:
var names = personRecod.Where(b=> b.Name == "Sam");
If you are looking to match partial contents then use Contains like:
var names = personRecod.Where(b=> b.Name.Contains("Sam"));
To compare partial content with ignoring case use IndexOf like:
var names = personRecod.Where(b=> b.Name.IndexOf("Same", StringComparison.InvariantCultureIgnoreCase) > -1);
.Any returns a boolean, true/false, for whether any item in that collection satisfies your condition. If you changed your var names to the type you expected to receive (string) then you'd receive an error highlighting this.
As has been stated, what you are looking for is just the .Where method, or possibly a .FirstOrDefault or .First.
If you are just looking for the third item (as it's the only one having a name containing the complete word 'Sam') then:
var names = personRecord
.Where(p => p.Name.Split(new char[] {' '}).Contains("Sam"));
I'm trying to construct a Where clause for a Linq statement which needs to determine whether the AccountNumber values retrieved as below exist in a List<string> collection.
I've thus far tried this:
private void FindAccountNumbers(List<string> AccountNumbers)
{
var query = from abc
select new
{
AccountNumber = abc.AccountNumber
};
query = query.Where(AccountNumbers.Contains(x => x.AccountNumber));
}
However I get the following build error:
The type arguments for method
'System.Linq.Queryable.Where(System.Linq.IQueryable,
System.Linq.Expressions.Expression>)' cannot
be inferred from the usage. Try specifying the type arguments
explicitly.
At runtime, query contains AccountNumber values, and I'm trying to pare this down based on matches found in the AccountNumbers collection (similar to an IN statement in TSQL). Should I be using Intersect instead of Contains? What am I doing wrong??
I think you want to have this:
query = query.Where(x => AccountNumbers.Contains(x.AccountNumber));
This doesn't work?
var query = from x in abc
where AccountNumbers.Contains(x.AccountNumber)
select new { x.AccountNumber };
That would give you back any AccountNumber in that list, unless AccountNumber isn't actually a string. That could be your problem.
Its because your syntax for from is wrong, I'm guessing that your collection is abc of items to match against is abc
The correct syntax would be (Version 1)
var query = from x in abc
select new { AccountNumber = x.AccountNumber };
query = query.Where(x=>AccountNumbers.Contains(x.AccountNumber));
you don't need to do an anonymous type either as you are just wanting the same field you could just do (Version 2)
var query = from x in abc select x.AccountNumber;
query = query.Where(x=>AccountNumbers.Contains(x));
However you could just slap the Where straight onto your original collection. (Version 3)
var query = abc.Where(x=>AccountNumbers.Contains(x.AccountNumber);
Or if you are just trying to find whether any exist in the collection (Version 4)
var query = abc.Any(x=>AccountNumbers.Countains(x.AccountNumber);
Version 1 will return IEnumerable<string>
Version 2 will return IEnumerable<string>
Version 3 will return IEnumerable<type of the items in abc>
Version 4 will return bool
Let me verify what you're trying to do.
You have a collection of objects abc. You want to pull out the AccountNumber from each member of that collection, compare it to the list of account numbers passed in, and determine... what? If there IS any overlap, or WHAT the overlap is?
If the AccountNumber field is a string, you could do this:
private IEnumerable<string> OverlappingAccountNumbers(IEnumerable<string> accountNumbers)
{
return abc.Select(x => x.AccountNumber)
.Intersect(accountNumbers);
}
Or for the boolean case:
private bool AnyOverlappingAccountNumbers(IEnumerable<string> accountNumbers)
{
return abc.Select(x => x.AccountNumber)
.Intersect(accountNumbers)
.Count() > 0;
}
I'd go with this:
private void FindAccountNumbers(List<string> AccountNumbers)
{
// Get a strongly-typed list, instead of an anonymous typed one...
var query = (from a in abc select a.AccountNumber).AsEnumerable();
// Grab a quick intersect
var matched = query.Intersect(AccountNumbers)
}
One liner?
var query = (from a in abc select a.AccountNumber).AsEnumerable().Intersect(AccountNumbers);
The last answer are wrong because did mention one important point and obviously didn't be tested, the first issue is, you can't mix between an sql query than not been execute and a string's list, YOU CAN'T MIX!!! the solution for this problem and tested is:
var AccountNumbers = select accountNumber from table where.... // is a entitie
private void FindAccountNumbers(IQueryable<acounts> AccountNumbers) //entitie object not string
{
var query = from abc
select new
{
AccountNumber = abc.AccountNumber
};
query = query.Join(AccountNumbers, abc => abc.AccountNumber, aco=> aco, (ac, coNum) => cpac);
}
It really works! is necessary to mention this solution is when you are working with linq and entities framework!
I have a scenario where I have to change the order by field based on some condition.
from summaryRows in _summaryTable.AsEnumerable()
where summaryRows.Field<string>("AirlineDisplayName")
.Equals(airlineName_, StringComparison.OrdinalIgnoreCase)
orderby summaryRows.Field<decimal>("FareAdult")
select new
{
summaryTableRow = summaryRows
};
Based on the condition, I have to change the order by field to orderby summaryRows.Field<double>("BasePricePlusTaxAndFees")
Here, both the field data type is different. How can I do it in one query?
I think this will be the most readable using fluent Linq syntax and introducing an if-statement while building the query.. Since you do not explain your condition, I assume that you have a boolean variable called condition with the appropriate value:
var query = _summaryTable.AsEnumerable()
.Where(
summaryRows => summaryRows.Field<string>("AirlineDisplayName")
.Equals(airlineName_, StringComparison.OrdinalIgnoreCase));
if (condition)
query = query.OrderBy(summaryRows => summaryRows.Field<decimal>("FareAdult"));
else
query = query.OrderBy(summaryRows => summaryRows.Field<double>("BasePricePlusTaxAndFees"));
var resultQuery = query.Select(summaryRows => new
{
summaryTableRow = summaryRows
});
Disclaimer: I have not tested it, but good luck.
What about this:
orderby conditionIsTrue ? (IComparable)summaryRows.Field<double>("BasePricePlusTaxAndFees") : (IComparable)summaryRows.Field<decimal>("FareAdult")
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();