Linq to XML Remove multiple returns - c#

Hi have a Linq Query to extract some information. Following is the part of it.
node = "DocumentClass";
AVariable="Something"
na="NA";
var documentClassesScript = (from documentClass in configparentXML.Descendants(node)
where documentClass.Attribute("Name").Value.Contains(AVariable)
select new ReadingXmlWithLinq
{
CustomStorageString = documentClass.Element("ValidationPluginAssociations") != null ? documentClass.Descendants("ValidationPluginAssociation").Attributes("CustomStorageString").Single().Value : na,
}
).Distinct();
In Some case i got following error
Sequence contains more than one
element
The reason is ValidationPluginAssociations contain more than one ValidationPluginAssociation. I need to distinct and get only one of them. Is there any way to get it.

if there is no need to have single object you can use First:
documentClass.Descendants("ValidationPluginAssociation")
.Attributes("CustomStorageString").First().Value

Related

Searching String to Xml file in C#

<AccessUrl>
<Url>/User/Index</Url>
<Url>/EmailAccounts/Index</Url>
<Url>/Registration/Index</Url>
</AccessUrl>
I have a xml file. I wand to search a string in it. I have written a C# code for it.
string Url="/User/Index";// or One of the above value from file.
var CheckPermission = (from a in doc.Elements("AccessUrl")
where a.Element("Url").Value.Contains(Url)
select a).Any();
but it only works OK with first Url value from file. But if i change the string Url="/EmailAccounts/Index";. It doesn't show any match even the url value exists in xml file.Well i tried a lot but didn't get succeed yet.
This is because a.Element("Url") gives you the first child element with specified name. You should go through all children instead with something like:
a.Elements("Url").Any(u => u.Value.Contains(Url))
This is because you are calling:
where a.Element("Url")
This will return the first matching element.
From the docs:
Gets the first (in document order) child element with the specified System.Xml.Linq.XName
You need to use something like this to check all elements:
var CheckPermission = (from a in doc.Descendants("Url")
where a.Value.Contains(Url)
select a).Any();
This appears to work.
string url="/EmailAccounts/Index";// or One of the above value from file.
var checkPermission = xml.Elements("AccessUrl").Elements("Url").Any(x => x.Value == url);

Using C # LINQ to Select within 2 tags that has a descendant node equal to a certain value?

I'm trying to select all objects within 2 tags specifically <AR>'s that contains an element that's a descendant of <AR>: <RL> with a certain value say 2. <RL> can be buried an arbitrary number of levels within <AR>'s, but will always be within <AR>. How can I do this in LINQ?
EX1:
<ARS>
<AR>
<EI> </EI>
<RL>5</RL>
</AR>
<AR>
<EI> </EI>
<RL>2</RL>
</AR>
</ARS>
Result :
<AR>
<EI> </EI>
<RL>2</RL>
</AR>
I tried using
IEnumerable<XNode> test_var = from result in doc.Descendants("AR")
where result.DescendantNodes()
But go from here, but this threw an error msg
var test_var = from result in doc.Descendants("AR")
where result.Descendants("RL").Any(x => (int)x == 2)
select result;
First problem is you need a select statement, such as adding select result.
Additionally your where needs to be a boolean. It sounds like you are looking for existence, which is frequently handled via the Any() extension method.
var searchString = "2";
IEnumerable<XElement> test_var = from result in doc.Descendants("AR")
where result.Descendants("RL").Any(xelm => xelm.Value == searchString)
select result;

Dapper Multiple Results From single query

Hi i am trying to get to grips with Dapper.
My situation is i want to pull two values from a query into two separate strings. Im not sure if i am going about this in the correct way, but this is what i am doing:
string sql = #"Select type, name
FROM ZipData
WHERE Zip = #zip";
using (var multi = conn.QueryMultiple(sql, new { zip = zip }))
{
string result = multi.Read<string>().SingleOrDefault();
}
And i am getting Cannot access a disposed object. Object name: 'GridReader'. when trying to read the second string.The thing is it gets the first value correctly and has both the fields in in the reader i am trying to get. Im sure im misusing the api.
What am i doing wrong here? Ive googled but can find a specific example.
You are mis-using QueryMultiple. That is defined for compound SQL statements that return multiple result sets. Something like:
SELECT Foo FROM MyTable;
SELECT Bar FROM MyOtherTable;
On the other hand, you are trying to get two different columns from a single result set, so you should just use the normal Query method:
var result = conn.Query(sql, new { zip = zip }).Single();
var type = result.type;
var name = result.name;
Query returns an enumerable (because generally a query can return multiple rows). It appears that you only want one row, however, so we invoke .Single at the end to just get that row. From there, the return type is dynamic so you can simply refer to the properies implied by the columns in your SELECT statement: type and name.

How to group then select elements into new class in LINQ (C# preferably)

Hi I am trying to get my head around grouping, and then building my own class in the result. I know the result of a group by is an IGrouping collection but can I access the rows as they are being built to add a couple of flags to them with a custom class?
I have a class called FlightTimes with some data, but I'd like to append some data to the rows, like a FlagRedEye. So I created a class called FlightTimeResult with the original FlightTime class data plus the flag.
Can I do this? I can't seem to figure out how to get it to work. I like to use strong types until I understand what is going on. I had to change a few things to protect my client so I apologize for any syntax errors.
IGrouping<string, FlightTimeResult> FlightTimes =
( from flighttimes in schedules.FlightTimes
group flighttimes by flighttimes.FlightType.ToString()
into groupedFlights
select new FlightTimeResult( )
{
FlightTimeData = FlightTime, // Original class data
FlagRedEye = (FlightTime.departureTime.Hour >= 0 &&
FlightTime.departureTime.Hour < 6) // Extra flag
} )
The goal is to have a collection of FlightTimesResult (FlightTime + extra flag) grouped by FlightType. Not sure how to access the individual FlightTime rows in the query 'select new FlightTimeResult()'
Do i need to use a nested query on the groupedFlights?
Thank you very much.
It is easiest achieved by calling Linq functions explicitly in following way:
IQueryable<IGrouping<string, FlightTimeResult>> query
= schedules.FlightTimes.GroupBy(
ft => ft.FlightType.ToString(), // key
ft => new FlightTimeResult() { // your constructed objects for key
FlightTimeData = ft,
FlagRedEye = (ft.departureTime.Hour >= 0 && ft.departureTime.Hour < 6)
}
);
The two-argument GroupBy operator function takes two lambdas as arguments - one for extracting keys, second for extracting values for it.
Also keep in mind that group by operation (be it group itm by key construction or GroupBy call) returns a collection of IGrouping<,>s - not a single one.
Thus it will be IEnumerable<IGrouping<,>> or IQueryable<IGrouping<,>>.
I think you're on the right track. Instead of grouping FlightTimes by FlightType, try building FlightTimeResults and grouping those by FlightType instead:
var results =
from ft in schedules.FlightTimes
group new FlightTimeResult
{
FlightTimeData = ft,
FlagRedeye = ft.DepartureTime.Hour >= 0 && ft.DepartureTime.Hour < 6
}
by ft.FlightType.ToString()
into groupedFlights
select groupedFlights;

LINQ to returns count even the list is empty

I have this block of code inside another LINQ statement.
VideoLinks = (from video in m.VideoLinks.DefaultIfEmpty(new VideoGallery())
orderby video.CreatedDate
select new VideoGallery()
{
Source = video.Source,
Type = video.Type,
Links = video.Links,
Title = video.Title
}).ToList()
unfortunately if dont use DefaultIfEmpty its through me an exception. If I use DefaultIfEmpty i give count as 1 for videolinks even if m.VideoLinks is null.
So now how can avoid getting count 1 if m.VideoLinks is null
DefaultIfEmpty is going to give you a default value. It counts as an item when you call ToList() on it...thus your count is 1.
This looks like you are using linq-to-objects, so you should add a where video != null
VideoLinks = (from video in m.VideoLinks
where video != null
orderby video.CreatedDate
select new VideoGallery()
{
Source = video.Source,
Type = video.Type,
Links = video.Links,
Title = video.Title
}).ToList()
wllmsaccnt is correct - your problem is the "DefaultIfEmpty" portion of your statement. By definition, you are requesting that there be at least one item in the collection, according to the definition of this method:
Returns the elements of the specified sequence or the specified value
in a singleton collection if the sequence is empty
I think the important question here is what exception are you receiving when you don't use DefaultIfEmpty? If you tell us that, perhaps we can help you avoid it...

Categories

Resources