AngleSharp - Find innermost nested tables - linq

I try to get a list of all innermost tables with AngleSharp. This tables doesn't contain any tables.
With HtmlAgilityPack I've realised it this way:
var wrapper = html.DocumentNode.SelectSingleNode(".//td[#class='wrapper']");
var innerMostTables = wrapper.SelectNodes(".//table [not(descendant::table)]");
With AngleSharp I've tried this, but it doesn't work:
var parser = new HtmlParser();
var document = parser.Parse(html);
var wrapper = document.All.Where(d => d.ClassName == "wrapper");
var innerMostTables = wrapper.Where(w => w.Descendents()
.Select(c => c.NodeName == "table").Count() == 0);

I could solve the problem:
foreach (IElement ch in wrapper.Descendents()
.Where(d => d.NodeName == "TABLE" && d.Descendents()
.Where(d2 => d2.NodeName == "TABLE").Count() == 0))
{
Console.WriteLine(ch.OuterHtml);
}

Related

LinqKit Core PredicateBuilder not functioning correctly

I have this query:
var query = LinqKit.PredicateBuilder.New<Resume>();
if (selectedWorkFieldID != 0)
{
query = query.And(js => js.WorkFieldID == selectedWorkFieldID);
if (!(selectedJobIDs.Contains(0) && selectedJobIDs.Count() == 1))
{
foreach (int jobID in selectedJobIDs)
query = query.Or(js => js.JobID == jobID);
}
}
var finalQuery = context.Resumes.AsNoTracking().Include(r => r.ResumeSkills)
.ThenInclude(rs => rs.Skill).Include(r => r.JobSeeker).ThenInclude(r => r.Profile)
.AsExpandable().Where(query);
count = finalQuery.Count();
resumes = finalQuery.Skip(args.Skip.Value).Take(args.Top.Value).ToList<Resume>();
This query returns All resumes not filtered ones. When I debug, the debugger curser enters the foreach block that filters with or, and there is one jobID in selectedJobIDs but the query returns all resumes. it seems the predicate builder not working at all. How to solve this?
I changed code to this:
if (selectedWorkFieldID != 0)
{
query = query.And(js => js.WorkFieldID == selectedWorkFieldID);
if (!(selectedJobIDs.Contains(0) && selectedJobIDs.Count() == 1))
{
var query2 = LinqKit.PredicateBuilder.New<Resume>();
foreach (int jobID in selectedJobIDs)
query2 = query2.Or(js => js.JobID == jobID);
query.And(query2);
}
}
and it is corrected.

Linq # Where clause with multiple condition

this is my export ui
this is my code:
var wrlist = db.Tbl_WorkRequest.ToList().Where(c => c.WR_Status == wrstatus &&
(wrtype.Length != 0) &&
c.WR_Family == wrfamily &&
wrfamily.Length!=0)
.Select(d => new {
WR_Title = d.WR_Title.ToString(),
WR_Type = d.WR_Type.ToString(),
WR_Family = d.WR_Family.ToString(),
WR_Status = d.WR_Status.ToString(),
WR_LocationAsset = d.WR_LocationAsset.ToString(),
WR_AssetName = d.WR_AssetName.ToString(),
WR_Requestor = d.WR_Requestor.ToString()
});
the problem is if I only choose zone in dropdownlist:family it generates correct list.
but when I choose dropdownlist:family&status it generates nothing.
this is the table:
I would change your code to check each filter criteria and add the appropriate filter, then convert to a list:
var wrq = db.Tbl_WorkRequest.AsQueryable();
if (wrstatus.Length > 0)
wrq = wrq.Where(wr => wr.WR_Status == wrstatus);
if (wrfamily.Length > 0)
wrq = wrq.Where(wr => wr.WR_Family == wrfamily);
var wrlist = wrq.Select(d => new {
WR_Title = d.WR_Title.ToString(),
WR_Type = d.WR_Type.ToString(),
WR_Family = d.WR_Family.ToString(),
WR_Status = d.WR_Status.ToString(),
WR_LocationAsset = d.WR_LocationAsset.ToString(),
WR_AssetName = d.WR_AssetName.ToString(),
WR_Requestor = d.WR_Requestor.ToString()
})
.ToList();

How to do a cascading IGrouping?

I'm trying to do a cascading groupby, but I can't find a way to get the proper index in the end (the .ElementAt(0) in the end of the code is wrong, in all 3 levels of hierarchy).
//Level
//---|Category
//---|---|Family
//---|---|---|Type
//---|---|---|---|Leaf
var leafs = queryLeafs.ToList();
foreach (var leaf in leafs)
{
//Get Type
var leafAttr = leaf.ObjectsEav.First(eav => eav.Attribute.Name == "parent");
long typeId = leafAttr.Value.Value;
leaf.Type = universe.First(o => o.Id == typeId);
//Family
var typeAttr = leaf.Type.ObjectsEav.First(eav => eav.Attribute.Name == "parent");
long familyId = typeAttr.Value.Value;
leaf.Family = universe.First(o => o.Id == familyId);
//Category
var familyAttr = leaf.Family.ObjectsEav.First(eav => eav.Attribute.Name == "parent");
long categoryId = familyAttr.Value.Value;
leaf.Category = universe.First(o => o.Id == categoryId);
}
var groupType = leafs.GroupBy(leaf => leaf.Type);
var groupFamily = groupType.GroupBy(t => **t.ElementAt(0)**.Family);
var groupCategory = groupFamily.GroupBy(f => **f.ElementAt(0).ElementAt(0)**.Category);
Can someone provide a light in my dark path?
If you have any suggestion on how to improve this question, I would appreciate with all my heart.

LINQ: query very slow

I have the following database structure (just showing the pertinent tables):
I need to get a listing of all the elements in the table "Propietario" and each element must have a list of all its related elements in "Clave". Specifically, I need the field "CodigoClave" from "Clave".
Also, I need to be able to filter the results any of the fields.
This is what I've come up with so far:
int pageSizeP = (pageSize == null || pageSize == 0 || pageSize > 15) ? 15 : (int)pageSize;
int pageNumberP = (pageNumber == null || pageNumber == 0) ? 1 : (int)pageNumber;
var propietariosCount = context.Propietarios.Count();
var propietariosQuery = context.Propietarios
.AsEnumerable()
.OrderBy(p => p.Nombre).ThenBy(p => p.Apellido1).ThenBy(p => p.Apellido2)
.Select(p => new
{
Id = p.Id,
Nombre = p.Nombre,
Apellido1 = p.Apellido1,
Apellido2 = p.Apellido2,
NIF = p.NIF,
Claves = string.Join(", ", context.PropietariosFincas
.Where(pf => pf.PropietarioId == p.Id)
.Join(context.Expedientes
.Include(e => e.Clave),
pf => pf.FincaId,
e => e.FincaId,
(pf, e) => (e.Clave.CodigoClave + ((e.Clave.Alias == null) ? "" : " - " + e.Clave.Alias))
).Distinct().ToList())
// Getting an array of Claves would do;
// I could turn it into a string in the JS app
// But it's just as slow
});
if (criteriosBusqueda != "")
{
string[] aCriterios = criteriosBusqueda.Split(new string[] { "," }, StringSplitOptions.None);
CompareOptions compareOptions = CompareOptions.IgnoreCase;
if (aCriterios[0] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Nombre != null)
.Where(p => p.Nombre.Replace("/", "__").ContainsIgnoreAccents(aCriterios[0], compareOptions));
if (aCriterios[1] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Apellido1 != null)
.Where(p => p.Apellido1.Replace("/", "__").ContainsIgnoreAccents(aCriterios[1], compareOptions));
if (aCriterios[2] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Apellido2 != null)
.Where(p => p.Apellido2.Replace("/", "__").ContainsIgnoreAccents(aCriterios[2], compareOptions));
if (aCriterios[3] != "")
propietariosQuery = propietariosQuery
.Where(p => p.NIF != null)
.Where(p => p.NIF.Replace("/", "__").ToLower().Contains(aCriterios[3].ToLower()));
if (aCriterios[4] != "")
propietariosQuery = propietariosQuery
.Where(p => p.Claves != null)
.Where(p => p.Claves.Replace("/", "__").ToLower().Contains(aCriterios[4].ToLower()));
}
var propietariosList = propietariosQuery.Skip((pageNumberP - 1) * pageSizeP).Take(pageSizeP)
.ToList();
var datosPropietarios = new
{
pageSize = pageSizeP,
pageNumber = pageNumberP,
recordsNumber = propietariosQuery.Count()
titulares = propietariosList
};
return Ok(datosPropietarios);
It works, but it's too slow (it takes several minutes). I've managed to make the initial query (the first page, unfiltered) fast by making recordsNumber = context.Propietarios.Count() but that breaks the pagination when filtering. And anyway, if I filter or if I go to a page near the end, it is again really slow.
How can I make the query faster?
My guess is that the query is pretty much traversing all the tables, so I don't know if there's even a solution that doesn't involve changing the data model.
It's because you are calling AsEnumerable, you are fetching all the data from Propietarios table to memory and the rest of operations you do after you call that method are executed using Linq to Objects instead of Linq to Entities, so your query is not translated to sql. Try removing it
Take a look of this post in case you need more info how AsEnumerable works with EF

Unable to cast object of type 'System.Collections.Generic.HashSet`1[libraryWebProject.Major]' to type 'libraryWebProject.Major'

I have this code in the code behind file
LibraryArticlesEntities la = new LibraryArticlesEntities();
int id = 17;
if (Request.QueryString["TitleID"] != null)
{
id = Int32.Parse(Request.QueryString["TitleID"]);
}
var gettitle = la.Titles.Where(t => t.ID == id).Select(t => t.Title1);
header.InnerHtml += gettitle;
var sub = la.Titles.Where(t => t.ID == id).Select(t => t.Majors);
foreach (Major major in sub) // the error is here
{
subject.InnerHtml += major.MajorName + " ";
}
Here I'm using a LINQ query to fetch a list of majors but I get this error when I try to iterate over it and display their names:
Unable to cast object of type 'System.Collections.Generic.HashSet`1[libraryWebProject.Major]' to type 'libraryWebProject.Major'.
The relationship between Title and Major is many to many and I have an association table linking Title ID and Major ID
Please try to make sub a List<Major> by adding .ToList(); at the end of your select.
var sub = la.Titles.Where(t => t.ID > 0)
.SelectMany(a => a.Majors.Select(b=>b)).ToList();
This line:
var sub = la.Titles.Where(t => t.ID == id).Select(t => t.Majors);
and the fact that "The relationship between Title and Major is many to many"
implies that the result of the Select is a collection of collections, so your loop will have to be:
foreach (var listOfMajors in sub)
{
foreach (var major in listOfMajors)
{
// Do stuff
}
}
Old answer replaced after it was revealed that the question didn't actually include the code that was in error.
Please try with ToList() and use var in foreach:
var sub = la.Titles.Where(t => t.ID == id)
.Include(t => t.Majors)
.Select(t => t.Majors).ToList();//use tolist() here
foreach (var major in sub) // and add var here please
{
subject.InnerHtml += major.MajorName + " ";
}

Resources