filter based on parent attribute - linq

I am looking for some help with buliding a LINQ query. i want to get all the Tabs for a particular datatype. I started builind the query but seems like still having some issue. Appreciate any feedback.Thanks Jay
<DataType name="WELL_INDUSTRY">
<Database key1="key1" key2="" delimeter="">
<Tabs>
<Tab>
<Name>Basic</Name>
var tabs = from tab in doc.Descendants("Tab")
where tab.Parent.Parent.Attribute("Name").ToString() == "WELL_INDUSTRY"
select new
{
Name = tab.Descendants("Name").First().Value
};
foreach (var tab in tabs)
Debug.WriteLine(tab.Name);

I would say, you're starting from the wrong side of the problem. Why don't you find <DataType> first, and then select all containing <Tab>s?
var tabs = from dt in doc.Descendants("DataType")
where (string)dt.Attribute("Name") == "WELL_INDUSTRY"
from tab in dt.Elements("Database").Elements("Tabs").Elements("Tab")
select new
{
Name = (string)tab.Elements("Name").First()
};
I would also recommend replacing doc.Descendants("DataType") with more strict match using Element/Elements with proper element names. It will make the query faster. I can't do that for you because I don't know whole document structure.

Related

Dynamic Linq on DataTable error: no Field or Property in DataRow, c#

I have some errors using Linq on DataTable and I couldn't figure it out how to solve it. I have to admit that i am pretty new to Linq and I searched the forum and Internet and couldn't figure it out. hope you can help.
I have a DataTable called campaign with three columns: ID (int), Product (string), Channel (string). The DataTable is already filled with data. I am trying to select a subset of the campaign records which satisfied the conditions selected by the end user. For example, the user want to list only if the Product is either 'EWH' or 'HEC'. The selection criteria is dynaically determined by the end user.
I have the following C# code:
private void btnClick()
{
IEnumerable<DataRow> query =
from zz in campaign.AsEnumerable()
orderby zz.Field<string>("ID")
select zz;
string whereClause = "zz.Field<string>(\"Product\") in ('EWH','HEC')";
query = query.Where(whereClause);
DataTable sublist = query.CopyToDataTable<DataRow>();
}
But it gives me an error on line: query = query.Where(whereClause), saying
No property or field 'zz' exists in type 'DataRow'".
If I changed to:
string whereClause = "Product in ('EWH','HEC')"; it will say:
No property or field 'Product' exists in type 'DataRow'
Can anyone help me on how to solve this problem? I feel it could be a pretty simple syntax change, but I just don't know at this time.
First, this line has an error
orderby zz.Field<string>("ID")
because as you said, your ID column is of type int.
Second, you need to learn LINQ query syntax. Forget about strings, the same way you used from, orderby, select in the query, you can also use where and many other operators. Also you'll need to learn the equivalent LINQ constructs for SQL-ish things, like for instance IN (...) is mapped to Enumerable.Contains etc.
With all that being said, here is your query
var productFilter = new[] { "EWH", "HEC" };
var query =
from zz in campaign.AsEnumerable()
where productFilter.Contains(zz.Field<string>("Product"))
orderby zz.Field<int>("ID")
select zz;
Update As per your comment, if you want to make this dynamic, then you need to switch to lambda syntax. Multiple and criteria can be composed by chaining multiple Where clauses like this
List<string> productFilter = ...; // coming from outside
List<string> channelFilter = ...; // coming from outside
var query = campaign.AsEnumerable();
// Apply filters if needed
if (productFilter != null && productFilter.Count > 0)
query = query.Where(zz => productFilter.Contains(zz.Field<string>("Product")));
if (channelFilter != null && channelFilter.Count > 0)
query = query.Where(zz => channelFilter.Contains(zz.Field<string>("Channel")));
// Once finished with filtering, do the ordering
query = query.OrderBy(zz => zz.Field<int>("ID"));

How to use #JDBCDBColumn for typ ahead in xpages

Using Notes 9 and extension library's data controls...
I want to use the #JDBCDbColumn() to get the type ahead values from an Oracle table.
Is that possible at all? Does it work the same way the standard DBColumn in the type ahead?
Note that the DBColumn is looking in a huge table, but I specify a where clause that should filter what the JDBCDBColumn returns.
Somehow, nothing happens. Work sfine with Notes data though, but I need to get this working with the Oracle data.
Thanks!
Update 1: Code I have...
#JdbcExecuteQuery(
"oracle",
"select distinct postal_code from cifadmin.postal_codes where postal_code like '"
+ getComponent("CodePostal").getValue() + "%'")
Update 2: Here is the code I have right now, but it doesn't return anything:
var CodePostal = getComponent("rsSearchQuery").getValue();
if(!!CodePostal) {
var params = [CodePostal];
var a = #JdbcDbColumn("oracle", "postal_codes", "postal_code", "postal_code like ?", params);
return #Unique(a);
} else {
return "--";
}
OK, I got it working thanks to all your comments and a bit of intuition!!!
Here is the working code:
var sql = "SELECT DISTINCT POSTAL_CODE FROM cifadmin.POSTAL_CODES WHERE POSTAL_CODE LIKE'" + getComponent("PostalCode").getValue() +"%' ORDER BY POSTAL_CODE";
var res = #JdbcExecuteQuery("oracle", sql);
var values = new Array();
while (res.next()) {
values.push(res.getString("POSTAL_CODE"));
}
return values;
The thing that got it working was when I have forced 'values' as an array. Without that, it just doesn't work.
Picky and sensitive, XPages are!!!
Thanks to all for your help ;)
Just tested it the first time ever: works fine for me except I didn't use a WHERE clause in my sample and another type of DB here.
<xp:inputText id="inputText1" styleClass="form-control">
<xp:typeAhead mode="partial" minChars="1" ignoreCase="true">
<xp:this.valueList><![CDATA[#{javascript:#JdbcDbColumn("postgres", "xpagesdemo.names", "lastname")}]]></xp:this.valueList>
</xp:typeAhead>
</xp:inputText>
See live demo here: http://www.notesx.net/postgres.nsf/typeahead.xsp
Ben, I think you mean you want to put the wildcard to the end of the parameter? Not sure of your data and if you are entering an exact match? Did you try:
var params = [CodePostal+ "%"];
Also, not sure if you need to enter "cifadmin.postal_codes" for your table as you did in your sql?
Howard

Linq to XML elements and descendants in the same search

Still learning Linq and had a problem trying to retrieve and element as well as descendants of another in the same select. I searched for a solution, but could not find what I was looking for and came up with a solution. But is it the right way to do it? Somehow, although it works, it does feel right.
I have the following XML structure:
<Tables>
<Table>
<SourceTable>WrittenRecordsTable</SourceTable>
<Researcher>Fred Blogs</Researcher>
<QuickRef>cwr</QuickRef>
<TableType>WrittenRecords</TableType>
<FieldMapping>
<RecordID>ID</RecordID>
<StartYear>StartYear</StartYear>
<EndYear>EndYear</EndYear>
<LastName>LastName</LastName>
<Title>Title</Title>
<Subject>Subject</Subject>
<Description>Reference</Description>
</FieldMapping>
</Table>
</Tables>
and the following Linq to XML:
var nodes = (from n in xml.Descendants("FieldMapping")
select new
{
SourceTable = (string)n.Parent.Element("SourceTable").Value,
RecordID = (string)n.Element("RecordID").Value,
StartYear = (string)n.Element("StartYear").Value,
EndYear = (string)n.Element("EndYear").Value,
LastName = (string)n.Element("LastName").Value,
Title = (string)n.Element("Title").Value,
Subject = (string)n.Element("Subject").Value
}).ToList();
It is the way I retrieve the SourceTable element that feels wrong. Am I worrying too much or is there a better way? Also, is it better to work with c# expressions rather than queries?
If your document structure always has to contain those nodes your query (and accessing SourceTable) is fine. It's fairly obvious of what's going on given reader knows how XML looks like.
However, if you want more top-down approach (which might seem more natural and easier to grasp), you can always query Table node first and store FieldMapping in a variable, but I wouldn't say it has any advantages over your approach:
var nodes = (from table in doc.Descendants("Table")
let fieldMapping = table.Element("FieldMapping")
select new
{
SourceTable = (string)table.Element("SourceTable").Value,
RecordID = (string)fieldMapping.Element("RecordID").Value,
StartYear = (string)fieldMapping.Element("StartYear").Value,
EndYear = (string)fieldMapping.Element("EndYear").Value,
LastName = (string)fieldMapping.Element("LastName").Value,
Title = (string)fieldMapping.Element("Title").Value,
Subject = (string)fieldMapping.Element("Subject").Value
}).ToList();

LinqToExcel - Need to start at a specific row

I'm using the LinqToExcel library. Working great so far, except that I need to start the query at a specific row. This is because the excel spreadsheet from the client uses some images and "header" information at the top of the excel file before the data actually starts.
The data itself will be simple to read and is fairly generic, I just need to know how to tell the ExcelQueryFactory to start at a specific row.
I am aware of the WorksheetRange<Company>("B3", "G10") option, but I don't want to specify an ending row, just where to start reading the file.
Using the latest v. of LinqToExcel with C#
I just tried this code and it seemed to work just fine:
var book = new LinqToExcel.ExcelQueryFactory(#"E:\Temporary\Book1.xlsx");
var query =
from row in book.WorksheetRange("A4", "B16384")
select new
{
Name = row["Name"].Cast<string>(),
Age = row["Age"].Cast<int>(),
};
I only got back the rows with data.
I suppose that you already solved this, but maybe for others - looks like you can use
var excel = new ExcelQueryFactory(path);
var allRows = excel.WorksheetNoHeader();
//start from 3rd row (zero-based indexing), length = allRows.Count() or computed range of rows you want
for (int i = 2; i < length; i++)
{
RowNoHeader row = allRows.ElementAtOrDefault(i);
//process the row - access columns as you want - also zero-based indexing
}
Not as simple as specifying some Range("B3", ...), but also the way.
Hope this helps at least somebody ;)
I had tried this, works fine for my scenario.
//get the sheets info
var faceWrksheet = excel.Worksheet(facemechSheetName);
// get the total rows count.
int _faceMechRows = faceWrksheet.Count();
// append with End Range.
var faceMechResult = excel.WorksheetRange<ExcelFaceMech>("A5", "AS" + _faceMechRows.ToString(), SheetName).
Where(i => i.WorkOrder != null).Select(x => x).ToList();
Have you tried WorksheetRange<Company>("B3", "G")
Unforunatly, at this moment and iteration in the LinqToExcel framework, there does not appear to be any way to do this.
To get around this we are requiring the client to have the data to be uploaded in it's own "sheet" within the excel document. The header row at the first row and the data under it. If they want any "meta data" they will need to include this in another sheet. Below is an example from the LinqToExcel documentation on how to query off a specific sheet.
var excel = new ExcelQueryFactory("excelFileName");
var oldCompanies = from c in repo.Worksheet<Company>("US Companies") //worksheet name = 'US Companies'
where c.LaunchDate < new DateTime(1900, 0, 0)
select c;

LINQ - How to do partial searches on multiple criteria using NHibernate.LINQ

I have a search page where a user can enter multiple cities seperated by a comma and we need to get all the real estate properties where the city is one that is entered in the search criteria. For instance the user will enter something like this
cities = Dallas, Austin
The query I have works fine if the user enters a full city name
var cityList = new List{"Dallas", "Austin"};
var properties = Reporsitory.AsQueryable
.Where(x=> cityList.Contains(x.City))
.ToList();
However if I just enter Dal, Aus it does not work. How can I make these partial searches work. Is Dynamic LINQ the only answer? Thanks!
try this
var cityList = new List{"Dallas", "Austin"};
var properties = Reporsitory.AsQueryable
.Where(x=> cityList.Contains(y => x.City.Contains(y)).ToList();
try to search inside the string, i hope it works
I don't know specifically for nHibernate, but Linq to SQL does support this:
.Where(x=> x.StartsWith("Dal"))
var properties = Reporsitory.AsQueryable().Where(x => cityList.Count(c => x.StartsWith(c)) != 0);
Or replace StartWith to Contains...

Resources