List of all different IfcEntities in IfcFile - c#

Summary
i have an ifc file with different IfcEntities like IfcWall, IfcBeam, IfcColumn etc.
i'm struggling to find a way to list all different entities in this ifc file
the list should contain every ifcentity occurence just once {"IfcWall", "IfcColumn", "IfcBeam", ...}
debugged also the code to see if there was any property which held the value i was searching for
My Code:
i've used the xbim Essential quick start guide
googled also
looked through the issues on github
using (var model = IfcStore.Open(_FilePath))
{
var allInstances = model.Instances;
var testList = model.Instances.OfType<IIfcBuildingElement>();
var nameList = new List<string>();
var objTypeList = new List<string>();
foreach (var item in testList)
{
var objType = item.IsTypedBy;
var firstObjType = objType.ElementAt(0);
var relType = firstObjType.RelatingType;
var name = item.Name;
nameList.Add(name);
}
}
What i expect:
simple list with all IfcEntities
like {"IfcWall", "IfcColumn", "IfcBeam", ...}
Would appreciate any help

thanks to #martin1cerny
the answer was quite simple:
var testList = model.Instances.OfType<IIfcBuildingElement>().GroupBy(e => e.GetType());
issue/question on github

Related

Returning list basic c sharp

I am new to programming and been tasked to grab data from an API.
The issue I have is basic C# returning the contents of brakeparts. I'm passing the part id and obtaining a list of brake parts correctly. I need to assign the partid to the list, which seems to work when adding a breakpoint, however how do I return this list? Return brake parts doesn't work. They could be potentially many parts it returns whilst looping I need it to append to the Parts list. I know its probably something quite simple but I can't get my head around returning back the whole list. I've tried brakeparts.AddRange(brakeparts); This doesn't work too.
private static List<Parts> getBrakeparts(List<int> partids)
{
var restClient = new RestClient("https://example.example.net/api");
foreach (var partid in partids)
{
var returnreq = new RestRequest($"/brakeparts/{partid}/ ", Method.GET);
var res = restClient.Execute(returnreq);
Parts brakeparts = JsonConvert.DeserializeObject<Parts>(res.Content);
brakeparts.PartID = partid;
}
return brakeparts;
}
As I understand, you're simply trying to return a list of parts which you want to fill with the Parts breakparts that you deserialized from the Json response.
Simply create a List<Parts> instance and add the breakparts to it in the loop.
It could look like the following.
private static List<Parts> getBrakeparts(List<int> partids)
{
var restClient = new RestClient("https://example.example.net/api");
List<Parts> parts = new List<Parts>();
foreach (var partid in partids)
{
var returnreq = new RestRequest($"/brakeparts/{partid}/ ", Method.GET);
var res = restClient.Execute(returnreq);
Parts brakeparts = JsonConvert.DeserializeObject<Parts>(res.Content);
brakeparts.PartID = partid;
parts.Add(brakeparts);
}
return parts;
}

How can i access to the Value that i scraped and Add it to my DataGrid? Pls Look at the screenshot

public void ScrapeData(string page)
{
var web = new HtmlWeb();
var doc = web.Load(page);
var Articles = doc.DocumentNode.SelectNodes("//*[#class = 'b-product-grid-tile js-tile-container']");
foreach (var article in Articles)
{
var Sneaker = HttpUtility.HtmlDecode(article.SelectSingleNode(".//span[#class ='b-product-tile-link js-product-tile-link']").InnerText);
var Preis = HttpUtility.HtmlDecode(article.SelectSingleNode(".//div[#class ='b-product-tile-price']").InnerText);
var hrefList = doc.DocumentNode.SelectNodes("//a").Select(p => p.GetAttributeValue("href", "not found"));
Debug.Print(Sneaker + Preis + hrefList);
_entries.Add(new EntryModel { Products = Sneaker, Preis = Preis, Link = hrefList }); // canĀ“t convert string implicitly (Sory i have Visual Studio in German i try to translate the Error)
}
All the Links But how can i access to them? and get them in my DataGrid
I found the Links but idk how i access to them and get it into my DataGrid
After i add .ToArray i got the same problem the Debugger Print alwayse (System.Linq.Enumerable+WhereSelectEnumerableIterator`2[HtmlAgilityPack.HtmlNode,System.String])
Here some screenshots of the edited code
Same Problem
The Edit Code
And again i am very sorry how i ask my questions i am very new and i am happy if you correct me
It's not completely clear which of the links you want; you've highlighted only one. However if you do:
var hrefList = doc.DocumentNode.SelectNodes("//a")
.Select(p => p.GetAttributeValue("href", "not found"))
.ToArray();
(added .ToArray())
Then you can access e.g. the second one via hrefList[1]
If you only ever want the second one you;d be better off doing:
var href = doc.DocumentNode.SelectNodes("//a")
.Select(p => p.GetAttributeValue("href", "not found"))
.Skip(1)
.First();
No need to copy the whole lot to an array if all you want is one

Why this difference between foreach vs Parallel.ForEach?

Can anyone explain to me in simple langauage why I get a file about 65 k when using foreach and more then 3 GB when using Parallel.ForEach?
The code for the foreach:
// start node xml document
var logItems = new XElement("log", new XAttribute("start", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss")));
var products = new ProductLogic().SelectProducts();
var productGroupLogic = new ProductGroupLogic();
var productOptionLogic = new ProductOptionLogic();
// loop through all products
foreach (var product in products)
{
// is in a specific group
var id = Convert.ToInt32(product["ProductID"]);
var isInGroup = productGroupLogic.GetProductGroups(new int[] { id }.ToList(), groupId).Count > 0;
// get product stock per option
var productSizes = productOptionLogic.GetProductStockByProductId(id).ToList();
// any stock available
var stock = productSizes.Sum(ps => ps.Stock);
var hasStock = stock > 0;
// get webpage for this product
var productUrl = string.Format(url, id);
var htmlPage = Html.Page.GetWebPage(productUrl);
// check if there is anything to log
var addToLog = false;
XElement sizeElements = null;
// if has no stock or in group
if (!hasStock || isInGroupNew)
{
// page shows => not ok => LOG!
if (!htmlPage.NotFound) addToLog = true;
}
// if page is ok
if (htmlPage.IsOk)
{
sizeElements = GetSizeElements(htmlPage.Html, productSizes);
addToLog = sizeElements != null;
}
if (addToLog) logItems.Add(CreateElement(productUrl, htmlPage, stock, isInGroup, sizeElements));
}
// save
var xDocument = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), new XElement("log", logItems));
xDocument.Save(fileName);
Use of the parallel code is a minor change, just replaced the foreach with Parallel.ForEach:
// loop through all products
Parallel.ForEach(products, product =>
{
... code ...
};
The methods GetSizeElements and CreateElements are both static.
update1
I made the methods GetSizeElements and CreateElements threadsafe with a lock, also doesn't help.
update2
I get answer to solve the problem. That's nice and fine. But I would like to get some more insigths on why this codes creates a file that is so much bigger then the foreach solutions. I am trying get some more sense in how the code is working when using threads. That way I get more insight and can I learn to avoid the pitfalls.
One thing stands out:
if (addToLog)
logItems.Add(CreateElement(productUrl, htmlPage, stock, isInGroup, sizeElements));
logItems is not tread-safe. That could be your core problem but there are lots of other possibilities.
You have the output files, look for the differences.
Try to define the following parameters inside the foreach loop.
var productGroupLogic = new ProductGroupLogic();
var productOptionLogic = new ProductOptionLogic();
I think the only two is used by all of your threads inside the parallel foreach loop and the result is multiplied unnecessaryly.

LINQ Query to get Column Headers in Silverlight

I am working on a Silverlight application using a WCF service where I need to get all the Column Headers from a specific table. I have been trying to write a LINQ query to do this, but so far I have not been able to get it to work correctly. I have not found very much information pertaining to this. I have found the following information, but I have had difficulties connecting to my data.
http://www.c-sharpcorner.com/UploadFile/dhananjaycoder/4856/#ReadAndPostComment
So far I have tried the following...This will not compile due to DataContext needing a parameter and that is where I am stuck.
public List<string> GetColumnHeaders()
{
DataContext context = new DataContext();
List<string> columnList = new List<string>();
var dataModel = context.Mapping;
foreach (var r in dataModel.GetTables())
{
if (r.TableName.Equals("table1", StringComparison.InvariantCultureIgnoreCase))
{
foreach (var c in r.RowType.DataMembers)
{
columnList.Add(c.MappedName);
}
}
}
return columnList;
}
Instead of using DataContext context = new DataContext();
I tried the following, but I know the problem is the same.
var dataModel = new AttributeMappingSource()
.GetModel(
typeof(RepositoryBase<HBS_SondesEntities>
));
Here is my best attempt at a solution, its hard to really understand what you have tried/written.
public List<string> GetColumnHeaders(){
List<string> columnList = new List<string>();
using (SondesEntities context = new HBS_SondesEntities()){
foreach (var r in context.Mapping.GetTables()){
if (r.TableName
.Equals("table1", StringComparison.InvariantCultureIgnoreCase)) {
foreach (var c in r.RowType.DataMembers){
columnList.Add(c.MappedName);
}
}
}
}
return columnList;
}
Assuming I didn't fat finger something here is the same code using linq.
public List<string> GetColumnHeaders(){
List<string> columnList = new List<string>();
using (SondesEntities context = new HBS_SondesEntities()){
var query = (
context.Mapping.GetTables()
.Where(t=>t.TableName
.Equals(
"table1",
StringComparison.InvariantCultureIgnoreCase)
)
).SelectMany(x=>x.RowType.DataMembers);
columnList = query.Select(m=>m.MappedName).ToList()
}
return columnList;
}
This might help:
http://jesseliberty.com/2009/08/13/linq-for-silverlight-developers/
I'm not sure what you mean by table, but if its a datagrid, the link should help.

Errors when creating a custom Querable object with MVC and Subsonic pagedlist

hiya, i have the following code but when i try and create a new IQuerable i get an error that the interface cannot be implemented, if i take away the new i get a not implemented exception, have had to jump back and work on some old ASP classic sites for past month and for the life of me i can not wake my brain up into C# mode.
Could you please have a look at below and give me some clues on where i'm going wrong:
The code is to create a list of priceItems, but instead of a categoryID (int) i am going to be showing the name as string.
public ActionResult ViewPriceItems(int? page)
{
var crm = 0;
page = GetPage(page);
// try and create items2
IQueryable<ViewPriceItemsModel> items2 = new IQueryable<ViewPriceItemsModel>();
// the data to be paged,but unmodified
var olditems = PriceItem.All().OrderBy(x => x.PriceItemID);
foreach (var item in olditems)
{
// set category as the name not the ID for easier reading
items2.Concat(new [] {new ViewPriceItemsModel {ID = item.PriceItemID,
Name = item.PriceItem_Name,
Category = PriceCategory.SingleOrDefault(
x => x.PriceCategoryID == item.PriceItem_PriceCategory_ID).PriceCategory_Name,
Display = item.PriceItems_DisplayMethod}});
}
crm = olditems.Count() / MaxResultsPerPage;
ViewData["numtpages"] = crm;
ViewData["curtpage"] = page + 1;
// return a paged result set
return View(new PagedList<ViewPriceItemsModel>(items2, page ?? 0, MaxResultsPerPage));
}
many thanks
you do not need to create items2. remove the line with comment try and create items2. Use the following code. I have not tested this. But I hope this works.
var items2 = (from item in olditems
select new ViewPriceItemsModel
{
ID = item.PriceItemID,
Name = item.PriceItem_Name,
Category = PriceCategory.SingleOrDefault(
x => x.PriceCategoryID == item.PriceItem_PriceCategory_ID).PriceCategory_Name,
Display = item.PriceItems_DisplayMethod
}).AsQueryable();

Categories