XML to Linq C#, no results - c#

I'm trying to grab the Filename from the below XML code where the partNum passed in by the end user matches the partNum of a JES.
My current code yields 0 results.
I will also be trying to grab the disrete attribute as well.
<JESs>
<JES partNum="116102440002" discrete="true">
<Filename>116-10244-0002_ILLK Collimator Cover Assy_Rev 3.docx</Filename>
</JES>
<JES partNum="116102440003" discrete="false">
<Filename>ILLK Collimator in Gimbal_Rev 4.docx</Filename>
</JES>
<JES partNum="116102440004" discrete="true">
<Filename>116-10244-0004_Collimator Cover Installation_Rev 1.docx</Filename>
</JES>
<JES partNum="116102440005" discrete="true">
<Filename>116-10244-0005_Collimator Lens Assembly_Rev 2.docx</Filename>
</JES>
</JESs>
C# Code
var FileName = (from n in xml.Descendants("JESs") where n.Element("JES").Attribute("partNum").Value == Convert.ToString(partNum) select n.Elements().Descendants().Elements()).ToList();

You can simplify (and fix) your query like this:
var partNumber = Convert.ToString(partNum);
var result = xml.Descendants("JES")
.FirstOrDefault(x => (string)x.Attribute("partNum") == partNumber);
if(result != null)
{
var fileName = (string)result.Element("Filename");
}

Shouldn't it be:
var FileNames = (from n in xml.Descendants("JESs")
where n.Element("JES").Attribute("partNum").Value == Convert.ToString(partNum)
select n.Element("JES").Element("Filename")).ToList();

Try this
var fileName = (from x in xml.Elements()
where x.Attribute("partNum").Value == "xxxx"
select x.Element("Filename").Value).FirstOrDefault();
//replace xxxx with actual value
If no elements found for given partNum, fileName will be null

Related

How to find exact matching number from comma separated string in LINQ

I have a column in database, it contains error codes like "2,3,7,5,6,17" and I have taken it as a string and I want to exact match digit using linq.
For example I want to find match 7 (This number is taking dynamically) inside this string then it will return true. But the problem is, string also contain 17 so its fetching row which contains 17 also even if 7 is not present. I have used Contains() for that. Kindly give me the exact solution of it so I can return rows where we got exact match inside this string.
Note: This string I am fetching from the Database using LINQ
Image to show Rows fetched from db
In this image you can see the number 17 row also fetched but it doesn't contain 7. I want only for the 7 (exact match only)
Code that I have used
List<TableModel> result = from DN in dbContext.Example where DN.ErrorType.Contains(ErrorTypetxt).Select({})
DN.ErrorType is a complete string fetched from the db i.e 2,3,7,5,6,17
ErrorTypetxt is a 7 that I want to exact match..
How to resolve this?
var num = 7;
var start = $"{num},";
var end = $",{num}";
var mid = $",{num},";
var same = $"{num}";
var query =
from dn in source
where
dn.ErrorType.StartsWith(start) ||
dn.ErrorType.Contains(mid) ||
dn.ErrorType.EndsWith(end) ||
dn.ErrorType == same
select dn;
Or
var num = 7;
var mid = $",{num},";
var query =
from dn in source
let modified = "," + dn.ErrorType + ","
where modified.Contains(mid)
select dn;
var expected = "7";
var queryResult = "1,2,17,7";
var splitResult = queryResult.Split(',');
bool result = !string.IsNullOrEmpty(splitResult.FirstOrDefault(s => string.Equals(s, expected)));
//returns true
You can solve this using split first and then use the contain.
Please check this
https://dotnetfiddle.net/80k13h
Update after the first comment:
use this structure
TestTables
.Where(x =>
("," + x.Subjects + ",").Contains(",7,") ||
(x.Subjects.EndsWith("7") && x.Subjects.Length == 1) ||
(x.Subjects.StartsWith("7,") && x.Subjects.Length == 2) ||
(x.Subjects.Contains(",7,") && x.Subjects.Length > 2 &&
x.Subjects[0] != '7' && x.Subjects[x.Subjects.Length - 1] != '7')
)
.ToList()
This generates the following SQL in linqpad as give the expected result.

How to remove spaces from linq data in C#

I have linq where data in one of column may have spaces or special character between string, for example my survey, your's survey. I need to remove this so after filtering linq should return mysurvey and yourssurvey
column I am interested to remove spaces and special character is consultation = consultation.Name
I am using C# .net core and entity framework
var query = (from consultation in Context.Consultations
join survey in Context.Surveys on consultation.Id equals survey.ConsultationId into surveys
select new
{
consultationId = consultation.Id,
consultation = consultation.Name,
surveyId = surveys.FirstOrDefault() == null? null : surveys.Select(x=>x.Id),
survey = surveys.FirstOrDefault() == null ? null : surveys.Select(x => x.Name),
subject ="survey"
});
If you want to remove spaces & special characters in a string use like below:
consultation = Regex.Replace(consultation.Name, "[^0-9A-Za-z]+", "");
Using namespace
using System.Text.RegularExpressions;
Write an extension method like this
public static string StripSpacesAndSpecialCharacters(this string text)
{
var specChars = new string[] { "'", ";" }; // add more spec chars here
var procesesedString = text.Trim();
foreach (var spec in specChars)
{
procesesedString = procesesedString.Replace(spec, string.Empty);
}
return procesesedString;
}
then use it in your query like
var query = (from consultation in Context.Consultations
join survey in Context.Surveys on consultation.Id equals survey.ConsultationId into surveys
select new
{
consultationId = consultation.Id,
consultation = consultation.Name.StripSpacesAndSpecialCharacters(),
surveyId = surveys.FirstOrDefault() == null? null : surveys.Select(x=>x.Id),
survey = surveys.FirstOrDefault() == null ? null : surveys.Select(x => x.Name),
subject ="survey"
});

Parse XML with Linq according to 2 values

I would like to know how to parse my xml file in c# with LinQ, I made a lot of research but there isn't my precise case..
So here is my xml code :
<WindowsMediaPlayer>
<Playlist name="playlistdefouf">
<Element>
<type>Audio</type>
<name>lol</name>
</Element>
<Element>
<type>Video</type>
<name>tamere</name>
</Element>
</Playlist>
</WindowsMediaPlayer>
I would like to make a function that verify if a song exists (With type AND name) according to the right playlist too.
For example if I got in parameters playlistname = "playlistdefouf",type = "Audio" and name = "lol" my function will return 1
I already tried to do something but I think I'm lost..
XDocument xmlFile = XDocument.Load(Helper.xmlFolder + "/playlist.xml");
IEnumerable<XElement> elem = xmlFile.Root.Descendants();
IEnumerable<XElement> requete = from d in elem
where d.Name == "Playlist"
&& d.Attribute("name").Value == "playlistdefouf"
select d;
IEnumerable<XElement> requete2 = from d in requete.Descendants()
where d.Name == "Element"
select d;
IEnumerable<XElement> requete3 = from d in requete2.Descendants()
select d;
Here is how to retrieve an IEnumerable of the Playlists that have a specific type and name:
XDocument xmlFile = XDocument.Load("playlists.xml");
var res = from playlist in xmlFile.Root.Elements("Playlist")
where
playlist.Attribute("name").Value == "playlistdefouf" &&
playlist.Element("Element").Element("type").Value == "Audio" &&
playlist.Element("Element").Element("name").Value == "lol"
select playlist;
You can get a count of the playlists by using the Count() extension method
res.Count();
Or you can use the Extension method Any() instead of Count to get a boolean that is more expressive if you want to know if a list contains any elements matching your parameters.
This yields the same result but I personally prefer it structured this way:
var xml = XDocument.Load("playlist.xml");
var result = from playlist in xml.Descendants("Playlist")
where (string)playlist.Attribute("name") == "playlistdefouf"
from song in playlist.Descendants("Element")
where (string)song.Element("type") == "Audio" && (string)song.Element("name") == "lol"
select playlist;
Then you can use the IEnumerable extensions to get the results you want:
var count = result.Count();
var isExisting = result.Any();
var playlist = result.ToList();

how to search string in Linq to SQL using contains

I am using below code to search a particular string in multiple columns
IEnumerable<UserProductDetailResult> _query
= from eml in dc.UserProductDetails
join zk in dc.ZeekUsers on eml.aspnet_User.UserId equals zk.UserId
where eml.aspnet_User.LoweredUserName.Equals(strUserName.ToLower())
&& (eml.Username.Contains(strSearch)
|| eml.ProductURL.Contains(strSearch)
|| eml.Nickname.Contains(strSearch))
&& !eml.IsDeleted
&& eml.IsActive
select new UserProductDetailResult
{
_userProductDetail = eml,
_zeekUser = zk
};
where dc is DataContext object.
but this returns 0 results.
the query that is generated from above code is
SELECT [t0].[UPID], [t0].[UserId], [t0].[PID], [t0].[Nickname], [t0].[Username], [t0].[ProductURL], [t0].[StartDt], [t0].[EndDt], [t0].[IsActive], [t0].[InfoData], [t0].[SocialNetworkingData], [t0].[AnalyticKey], [t0].[ProfileID], [t0].[UseDefaultAd], [t0].[UseDefaultEmail], [t0].[IsDeleted], [t0].[CreateDt], [t0].[LastUpdateDt], [t1].[ID], [t1].[UserId] AS [UserId2], [t1].[AccountType], [t1].[FirstName], [t1].[LastName], [t1].[Phone], [t1].[Address1], [t1].[Address2], [t1].[City], [t1].[State], [t1].[ZIP], [t1].[CountryID], [t1].[NickName1], [t1].[Nickname2], [t1].[AlternameEmail], [t1].[ProfileImage], [t1].[ZeekIdStatus], [t1].[RefZeekUserId], [t1].[IsActive] AS [IsActive2], [t1].[FailureCount], [t1].[IsBlocked], [t1].[IsFirstVisit], [t1].[IsWizardPassed], [t1].[IPAddress], [t1].[TimeZoneID], [t1].[CreateDt] AS [CreateDt2], [t1].[LastUpdateDt] AS [LastUpdateDt2]
FROM [dbo].[UserProductDetails] AS [t0]
INNER JOIN [dbo].[ZeekUsers] AS [t1] ON ((
SELECT [t2].[UserId]
FROM [dbo].[aspnet_Users] AS [t2]
WHERE [t2].[UserId] = [t0].[UserId]
)) = [t1].[UserId]
INNER JOIN [dbo].[aspnet_Users] AS [t3] ON [t3].[UserId] = [t0].[UserId]
WHERE ([t3].[LoweredUserName] = 'username') AND (([t0].[Username] LIKE 'a') OR ([t0].[ProductURL] LIKE 'a') OR ([t0].[Nickname] like 'a')) AND (NOT ([t0].[IsDeleted] = 1)) AND ([t0].[IsActive] = 1)
As soon as remove below search lines it works and returns ,
&& (eml.Username.Contains(strSearch)
|| eml.ProductURL.Contains(strSearch)
|| eml.Nickname.Contains(strSearch))
but this doesn't allow me to search
Can anyone please tell me how should I proceed?
By your generated query, I think you are using the linq-to-sql. You could use the SqlMethods.Like to generate the right like query operator, from MSDN:
Determines whether a specific character string matches a specified
pattern. This method is currently only supported in LINQ to SQL
queries.
For sample:
// first sample, any part of string
strSearch = string.Format("%[^a-zA-Z]{0}[^a-zA-Z]%", strSearch);
// on the end of the string
strSearch = string.Format("%[^a-zA-Z]{0}", strSearch);
//on the begining of the string
strSearch = string.Format("{0}[^a-zA-Z]%", strSearch);
in your query statemant..
(SqlMethods.Like(eml.Username, strSearch)
|| SqlMethods.Like(eml.ProductURL, strSearch)
|| SqlMethods.Like(eml.Nickname, strSearch))
Otherwise you could add the % char in your strSearch string before your query to result a query with information in any part of string, for sample:
strSearch = string.Contat("%", strSearch, "%");
I have create a nuget package that can help you here. It will enable you to use the following syntax:
var result = dc.UserProductDetails
.Where(eml => eml.IsActive && !eml.IsDeleted)
.Search(eml => eml.aspnet_User.LoweredUserName) // Search LoweredUsername
.IsEqual(strUserName) // when equals strUsername
.Search(eml => eml.UserName, // Search UserName
eml => eml.ProductURL, // OR ProductUrl
eml => eml.Nickname) // OR Nickname
.Containing(strSearch) // When contains strSearch
.Select(eml => new UserProductDetailResult // Build result...
{
_userProductDetail = eml
});
You can download the package from here
http://www.nuget.org/packages/NinjaNye.SearchExtensions
...also take a look at the GitHub page for more detailed information
Hope this helps

Using Intersect I'm getting a Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator

I'm using a Linq to SQL query to provide a list of search term matches against a database field. The search terms are an in memory string array. Specifically, I'm using an "intersect" within the Linq query, comparing the search terms with a database field "Description". In the below code, the description field is iss.description. The description field is separated into an array within the Linq query and the intersect is used to compare the search terms and description term to keep all of the comparing and conditions within the Linq query so that the database is not taxed. In my research, trying o overcome the problem, I have found that the use of an in-memory, or "local" sequence is not supported. I have also tried a few suggestions during my research, like using "AsEnumerable" or "AsQueryable" without success.
searchText = searchText.ToUpper();
var searchTerms = searchText.Split(' ');
var issuesList1 = (
from iss in DatabaseConnection.CustomerIssues
let desc = iss.Description.ToUpper().Split(' ')
let count = desc.Intersect(searchTerms).Count()
where desc.Intersect(searchTerms).Count() > 0
join stoi in DatabaseConnection.SolutionToIssues on iss.IssueID equals stoi.IssueID into stoiToiss
from stTois in stoiToiss.DefaultIfEmpty()
join solJoin in DatabaseConnection.Solutions on stTois.SolutionID equals solJoin.SolutionID into solutionJoin
from solution in solutionJoin.DefaultIfEmpty()
select new IssuesAndSolutions
{
IssueID = iss.IssueID,
IssueDesc = iss.Description,
SearchHits = count,
SolutionDesc = (solution.Description == null)? "No Solutions":solution.Description,
SolutionID = (solution.SolutionID == null) ? 0 : solution.SolutionID,
SolutionToIssueID = (stTois.SolutionToIssueID == null) ? 0 : stTois.SolutionToIssueID,
Successful = (stTois.Successful == null)? false : stTois.Successful
}).ToList();
...
The only way I have been successful is to create two queries and calling a method as shown below, but this requires the Linq Query to return all of the matching results (with the number of hits for search terms in the description) including the non-matched records and provide an in-memory List<> and then use another Linq Query to filter out the non-matched records.
public static int CountHits(string[] searchTerms, string Description)
{
int hits = 0;
foreach (string item in searchTerms)
{
if (Description.ToUpper().Contains(item.Trim().ToUpper())) hits++;
}
return hits;
}
public static List<IssuesAndSolutions> SearchIssuesAndSolutions(string searchText)
{
using (BYCNCDatabaseDataContext DatabaseConnection = new BYCNCDatabaseDataContext())
{
searchText = searchText.ToUpper();
var searchTerms = searchText.Split(' ');
var issuesList1 = (
from iss in DatabaseConnection.CustomerIssues
join stoi in DatabaseConnection.SolutionToIssues on iss.IssueID equals stoi.IssueID into stoiToiss
from stTois in stoiToiss.DefaultIfEmpty()
join solJoin in DatabaseConnection.Solutions on stTois.SolutionID equals solJoin.SolutionID into solutionJoin
from solution in solutionJoin.DefaultIfEmpty()
select new IssuesAndSolutions
{
IssueID = iss.IssueID,
IssueDesc = iss.Description,
SearchHits = CountHits(searchTerms, iss.Description),
SolutionDesc = (solution.Description == null)? "No Solutions":solution.Description,
SolutionID = (solution.SolutionID == null) ? 0 : solution.SolutionID,
SolutionToIssueID = (stTois.SolutionToIssueID == null) ? 0 : stTois.SolutionToIssueID,
Successful = (stTois.Successful == null)? false : stTois.Successful
}).ToList();
var issuesList = (
from iss in issuesList1
where iss.SearchHits > 0
select iss).ToList();
...
I would be comfortable with two Linq Queries, but with the first Linq Query only returning the matched records and then maybe using a second, maybe lambda expression to order them, but my trials have not been successful.
Any help would be most appreciated.
Ok, so after more searching more techniques, and trying user1010609's technique, I managed to get it working after an almost complete rewrite. The following code first provides a flat record query with all of the information I am searching, then a new list is formed with the filtered information compared against the search terms (counting the hits of each search term for ordering by relevance). I was careful not to return a list of the flat file so there would be some efficiency in the final database retrieval (during the formation of the filtered List<>). I am positive this is not even close to being an efficient method, but it works. I am eager to see more and unique techniques to solving this type of problem. Thanks!
searchText = searchText.ToUpper();
List<string> searchTerms = searchText.Split(' ').ToList();
var allIssues =
from iss in DatabaseConnection.CustomerIssues
join stoi in DatabaseConnection.SolutionToIssues on iss.IssueID equals stoi.IssueID into stoiToiss
from stTois in stoiToiss.DefaultIfEmpty()
join solJoin in DatabaseConnection.Solutions on stTois.SolutionID equals solJoin.SolutionID into solutionJoin
from solution in solutionJoin.DefaultIfEmpty()
select new IssuesAndSolutions
{
IssueID = iss.IssueID,
IssueDesc = iss.Description,
SolutionDesc = (solution.Description == null) ? "No Solutions" : solution.Description,
SolutionID = (solution.SolutionID == null) ? 0 : solution.SolutionID,
SolutionToIssueID = (stTois.SolutionToIssueID == null) ? 0 : stTois.SolutionToIssueID,
Successful = (stTois.Successful == null) ? false : stTois.Successful
};
List<IssuesAndSolutions> filteredIssues = new List<IssuesAndSolutions>();
foreach (var issue in allIssues)
{
int hits = 0;
foreach (var term in searchTerms)
{
if (issue.IssueDesc.ToUpper().Contains(term.Trim())) hits++;
}
if (hits > 0)
{
IssuesAndSolutions matchedIssue = new IssuesAndSolutions();
matchedIssue.IssueID = issue.IssueID;
matchedIssue.IssueDesc = issue.IssueDesc;
matchedIssue.SearchHits = hits;
matchedIssue.CustomerID = issue.CustomerID;
matchedIssue.AssemblyID = issue.AssemblyID;
matchedIssue.DateOfIssue = issue.DateOfIssue;
matchedIssue.DateOfResolution = issue.DateOfResolution;
matchedIssue.CostOFIssue = issue.CostOFIssue;
matchedIssue.ProductID = issue.ProductID;
filteredIssues.Add(matchedIssue);
}
}

Categories

Resources