How to get the values of this xml using linq? - linq

I have the following in my xml:
<mur>
<bak>
</bak>
<itemfb ident="c_fb">
<flow_m>
<mat>
<text texttype="text/plain">correct answer comments</text>
</mat>
</flow_m>
</itemfb>
<itemfb ident="gc_fb">
<flow_m>
<mat>
<text texttype="text/plain">wrong, you made a blunder</text>
</mat>
</flow_m>
</itemfb>
</mur>
Now, the 'itemfb' tag, may or may not exist within a 'mur' tag and if exists, I need to parse and get the values "correct answer comments" (or) "wrong, you made a blunder" depending on "itemfb" ident. Here is what I have tried. Assume rowObj has the loaded xml from "mur" and 'ns' is the namespace
if (rowObj.Elements(ns + "itemfb").Any())
{
var correctfb = (from cfb in rowObj
.Descendants(ns + "itemfb")
where (string)cfb.Attribute(ns + "ident").Value == "cfb"
select new
{
ilcfb = (string)cfb.Element(ns + "mat")
}).Single();
some_variable_1 = correctfb.ilcfb;
var incorrectfb = (from icfb in rowObj
.Descendants(ns + "itemfb")
where (string)icfb.Attribute(ns + "ident").Value == "gcfb"
select new
{
ilicfb = (string)icfb.Element(ns + "mat")
}).Single();
some_variable_2 = incorrectfb.ilicfb;
}

This should be a way to get the information you want. I omitted ns for simplicity.
var correctfb = rowObj.Descendants("mur")
.Descendants("itemfb")
.Where(e => e.Attribute("ident").Value == "c_fb")
.Descendants("text").FirstOrDefault();
if (correctfb != null)
some_variable_1 = correctfb.Value;
var incorrectfb = rowObj.Descendants("mur")
.Descendants("itemfb")
.Where(e => e.Attribute("ident").Value == "gc_fb")
.Descendants("text").FirstOrDefault();
if (incorrectfb != null)
some_variable_2 = incorrectfb.Value;

Related

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();

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

AngleSharp - Find innermost nested tables

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);
}

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 + " ";
}

Entity fails on simulataneous AJAX posts

I have an action that updates the database based on a Jquery Droppable/Sortable. The first AJAX post works fine, but the second one gives me the error:
New transaction is not allowed because there are other
threads running in the session.
It's being posted to 2 separate actions on the same controller, using the same UnitOfWork in the controller. Not sure what I have to do to fix this.
EDIT: these are the two service methods being called:
public void NavItemSort(List<string> orderArray, string navID, string subNavID)
{
var newOrderArray = orderArray.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
var orderArrayIDs = newOrderArray.Select(x => x.Replace("ContentItem", "")).ToList();
var itemToBeSorted = Convert.ToInt32(orderArrayIDs.FirstOrDefault());
var itemContext = cmsUnitOfWork.NavigationItems.Find().Where(x => x.ID == itemToBeSorted).ToList().FirstOrDefault();
var currentSortOrder = cmsUnitOfWork.NavigationItems.Find()
.Where(x => x.NavID == itemContext.NavID &&
(itemContext.ParentID == null) ? x.ParentID == null :
x.ParentID == itemContext.ParentID).ToList();
var existingItems = currentSortOrder.Select(x => x.ID).ToList();
List<string> existingItemsString = existingItems.ConvertAll<string>(x => x.ToString()).ToList();
var newNavItemID = existingItemsString.Except(orderArray).FirstOrDefault();
var currentSortOrderExcept = currentSortOrder.Where(x => x.ID != Convert.ToInt32(newNavItemID));
foreach (var x in currentSortOrderExcept)
{
int sortOrderInt = orderArrayIDs.IndexOf(orderArrayIDs.Where(z => int.Parse(z) == x.ID).ToList().FirstOrDefault()) + 1;
NavigationItem navigationItem = new NavigationItem()
{
HasChild = x.HasChild,
Level = x.Level,
NavID = x.NavID,
ID = x.ID,
ParentID = x.ParentID,
PageID = x.PageID,
URL = x.URL,
Title = x.Title,
SortOrder = sortOrderInt,
};
if (navigationItem.SortOrder != null && navigationItem.SortOrder != 0)
{
cmsUnitOfWork.NavigationItems.Update(x, navigationItem);
}
}
cmsUnitOfWork.Commit();
}
public void NavItemAdd(List<string> orderArray, string NavID, string subNavID){
var newOrderArray = orderArray.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
var orderArrayIDs = newOrderArray.Select(x => x.Replace("ContentItem", "")).ToList();
NavID = NavID.Replace("nav", "");
int NavIDInt = int.Parse(NavID);
int subNavIDInt = int.Parse(subNavID);
var existingNavItems = cmsUnitOfWork.NavigationItems.Find().Where(x => x.NavID == NavIDInt && x.ParentID == subNavIDInt).ToList();
int currentSortOrder = 0;
if (existingNavItems.Count() != 0)
{
currentSortOrder = existingNavItems.Max(x => x.SortOrder);
}
var existingItems = existingNavItems.Select(x => x.ID).ToList();
List<string> existingItemsString = existingItems.ConvertAll<string>(x => x.ToString()).ToList();
var newNavItemID = orderArray.Except(existingItemsString).FirstOrDefault();
int newNavIDInt = int.Parse(newNavItemID);
var newNavItemList = cmsUnitOfWork.NavigationItems.Find().Where(x => x.ID == newNavIDInt).ToList();
var newNavItem = newNavItemList.FirstOrDefault();
var parentNav = cmsUnitOfWork.NavigationItems.Find().Where(x => x.ID == subNavIDInt).ToList().FirstOrDefault();
NavigationItem navigationItemUpdated = new NavigationItem()
{
ID = newNavItem.ID,
Level = 2,
NavID = NavIDInt,
PageID = newNavItem.PageID,
Title = newNavItem.Title,
URL = newNavItem.URL,
ParentID = subNavIDInt,
SortOrder = currentSortOrder + 1
};
cmsUnitOfWork.NavigationItems.Update(newNavItem, navigationItemUpdated);
cmsUnitOfWork.Commit();
}
I'm guessing you started a transaction against that context and you never dispose of it not commit it. Just a guess though as you didn't Los any code (please post code)
Maybe you have declared cmsUnitOfWork as static variable? Context must be created and destroyed on each request

Resources