How to clear the contents of an IEnumerable - vb.net

Dim sortQuery = From results In resultList
Order By results.getUsername()
Where results.getUsername() = passUsername
Select results.getAll()
For Each Str As String In sortQuery
lstBox.Items.Add(Str)
Next
I have created a generic IEnumerable of objects. The object class is results, resultList is a list of many instances of that object. In order to carry out multiple queries, I intend to repeat this code but with different conditions.
When this code is repeated, it outputs results for that search in addition to all results from previous searches made. I believe that clearing the IEnumerable between queries will prevent this. Is there a way to do this? Alternatively, how could I make it so that each query outputs only the results for that query and not those for the previous ones as well?

You can't clear an IEnumerable(Of T). That interface just means that you can enumerate a list of items. It says nothing about how those items are stored. In the case of a LINQ query, it's not the items that are stored but information on how to get them from a source list. The list of items that results from executing the query is not stored separately anywhere to clear but is generated by applying the query logic each time.
If you want to execute similar but different queries then you need to create multiple queries. You can create a single base query that contains the common logic and then you can just apply the specific parts to each specific query. For instance, if you wanted to get all the Person objects from a list but you wanted the males and females separately then you could do this:
Dim baseQuery = From person In people
Where person.FamilyName = "Smith"
Dim maleQuery = From person In baseQuery
Where person.Sex = Sex.Male
Dim femaleQuery = From person In baseQuery
Where person.Sex = Sex.Female
All three of those queries are stored as logic, not as objects. When you enumerate maleQuery or femaleQuery, you are executing that logic and getting the results one by one. In each case, the logic stored in baseQuery is executed as well as the logic in the more specific query so you get both filters applied at the same time.
EDIT: I should clarify and say that you cannot clear an IEnumerable(Of T) via that interface. For instance, a List(Of T) implements the IEnumerable(Of T) interface and you can clear that, but it's that class that provides that functionality. If all you know about an object is that it implements IEnumerable(Of T) then you can't clear it because you have no idea if it has functionality besides that defined by that interface. A LINQ query definitely doesn't have such functionality because there's no actual concrete list to clear.

Related

LINQ result on datatable without for loop

I am sure this is easy (or that I am completely wrong), but all I want to do is get the single values against a LINQ query on a datatable and not use a for.. each loop to access them.
Scenario..
I have a datatable containing a number of rows. I run my query looking for a particular match on "EP" like such..
Dim qryB = From rw In oDT_Cables
Where rw("EP").Equals(br.Position)
Select ld = rw("LOAD"), tl = rw("TOT-LEN")
Now..
I know that I have only one result (due to checking upon insertion), so how do I simply access the items ld and tl without a for each loop??
I have tried:
qryb.elementat(1) error
qryb.elementat(ld) Not possible
qryb.tl not possible
Does anyone know how I can access tl and ld from the query please? It is much appreciated.
Brett
If you know for a fact that a LINQ query produces a single result then you call Single.
Dim result = qryB.Single()
If there may be no result but will never be more than one then you call SingleOrDefault and the result may be Nothing. If there will be at least one result but may be more and you want just the first, you call First. If there may be zero, one or more and you want the first if there is one then you call FirstOrDefault and the result may be Nothing.
Note that some LINQ providers don't support both options, e.g. LINQ to Entities (the LINQ provider for Entity Framework) supports First and FirstOrDefault but not Single or SingleOrDefault (unless it's changed recently) while, if I'm not mistaken, LINQ to SQL supports Single and SingleOrDefault but not First or FirstOrDefault.
Note that, if you were going to use ElementAt, you would have to specify 0 as the index. ElementAt works pretty much like indexing a array or other IList, so the first item is at index 0. You'd only use ElementAt for something in the middle of a query result though, given that you have Single, First and Last methods and their nullable equivalents.

NHibernate SQL Query mapping on Single Column Result

I have a very simple question but cannot find a simple answer.
I have NHibernate executing a raw SQL query, which unfortunately is loaded from the DB (yes, we store SQL query in the DB, not the best design but bear with me). This means that basically I have no idea how many columns the query will return.
What I know is that if the query is a single column then it is what I need and if it is more than one column then I need the first one, easy enough.
In my code I have basically 3 options:
session.CreateSQLQuery(SQLString).List();
session.CreateSQLQuery(SQLString).List<object>();
session.CreateSQLQuery(SQLString).List<object[]>();
Problem is that the List() will return either a List<int> (or the appropriate type, but int should be in my case) if the query returns a single column, or a List<object[]>() if I have multiple columns. Same goes for List<object> except that it will not return a List<int> in this case.
Of course trying to always cast to object[] (3rd option) and get the first element does not work, since nHibernate returns an int and that cannot be cast to object[].
Is there a way to force nHibernate to always return an object[] even in the case of a single column? If not, is there an easy way to check the number of columns in the result and act accordingly?
Thanks!
You should take a look at the differant result transformers NHibernate provides out of the box (you can write your own as well of course).
What might fit in your case would be the NHibernate.Transform.ToListResultTransformer. AFAIK, it transforms your result to an IList, where each entry contains an IList again.
So:
IList items = session
.CreateSQLQuery(query)
.SetResultTransformer(new NHibernate.Transform.ToListResultTransformer())
.List()
if(((Ilist)items[0]).Count == 1)
// just one columns
else
// more columns or zero

How to manage multiple tables with the same structure (redux)

I found this question, which is similar to a problem that I would like to solve:
How to manage multiple tables with the same structure
However, due to the craptastical nature of VB, the solution doesn't really work. It specifically doesn't work because VB.NET requires the implementation of each method/property in the interface to be explicitly declared.
As for the problem that I'm really trying to solve, here it is:
I have many lookup/domain tables in the database that all have the same structure
The items in these tables are typically used for drop downs in the interface
I would like to avoid a bunch of boilerplate repository methods to retrieve the contents of these tables (one method per table really sucks when you have 40 tables)
I am not using the One True Lookup Table anti-pattern and this is not an option
Does anyone have another solution for this that work work in VB?
Generic Repository should work in this case. There are many available online or you can write a simpler one for just the lookup tables.
Here is the code that we ended up using:
Public Function GetDomainTableList(tableName As String) As IEnumerable(Of Object)
Dim table = CType(GetType(FECEntities).GetProperty(tableName).GetValue(DB, Nothing), IEnumerable(Of Object))
Dim dt = From r In table
Select r
Return dt.ToList()
End Function
I had originally thought that this wouldn't work for us since I was trying to project each object returned into a DomainTableItem class that I had written. But then I realized that the SelectList constructor didn't really care about the type of object that it takes in. You just pass in a String containing the property name and it uses reflection to pull out the value.
So everything works out peachy this way and I avoided writing one method per domain/lookup table.

nhibernate: how to map aggregates

Good afternoon, I'm trying to learn nHibernate and it's not terribly clear.
I need to get the result of an sql query:
select patient.name,
discipline.description,
sum(patient.enddate - patient.startdate) as totaltime
from treatment
join patient on patient.id = treatment.patientId
join discipline.id = treatment.disciplineId
I don't need to persist the result, just display it.
If I use hql directly:
What objects will it instantiate and return to me? Will it dynamically build a list of objects containing fields identical to the columns in the result set? The docs leave out this information.
If I need to make a mapping:
Do you create a mapping to a 'meta' object or to one of the joined tables (say 'treatment')?
Thanks
This can be achieved by using DTO objects ("data transfer objects"). You create an object that contains only the data you wish to return. Add an initializing constructor. Then your hql can be of the form:
select new mydto( x.value, y.value ) from x join x.y;
It doesn't seem to like using aggregate functions in the object constructor though.

nhibernate and DDD suggestion

I am fairly new to nHibernate and DDD, so please bear with me.
I have a requirement to create a new report from my SQL table. The report is read-only and will be bound to a GridView control in an ASP.NET application.
The report contains the following fields Style, Color, Size, LAQty, MTLQty, Status.
I have the entities for Style, Color and Size, which I use in other asp.net pages. I use them via repositories. I am not sure If should use the same entities for my report or not. If I use them, where I am supposed to map the Qty and Status fields?
If I should not use the same entities, should I create a new class for the report?
As said I am new to this and just trying to learn and code properly.
Thank you
For reports its usually easier to use plain values or special DTO's. Of course you can query for the entity that references all the information, but to put it into the list (eg. using databinding) it's handier to have a single class that contains all the values plain.
To get more specific solutions as the few bellow you need to tell us a little about your domain model. How does the class model look like?
generally, you have at least three options to get "plain" values form the database using NHibernate.
Write HQL that returns an array of values
For instance:
select e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty
from entity1 inner join entity2
where (some condition)
the result will be a list of object[]. Every item in the list is a row, every item in the object[] is a column. This is quite like sql, but on a higher level (you describe the query on entity level) and is database independent.
Or you create a DTO (data transfer object) only to hold one row of the result:
select new ReportDto(e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty)
from entity1 inner join entity2
where (some condition)
ReportDto need to implement a constructor that has all this arguments. The result is a list of ReportDto.
Or you use CriteriaAPI (recommended)
session.CreateCriteria(typeof(Entity1), "e1")
.CreateCriteria(typeof(Entity2), "e2")
.Add( /* some condition */ )
.Add(Projections.Property("e1.Style", "Style"))
.Add(Projections.Property("e1.Color", "Color"))
.Add(Projections.Property("e1.Size", "Size"))
.Add(Projections.Property("e2.LAQty", "LAQty"))
.Add(Projections.Property("e2.MTLQty", "MTLQty"))
.SetResultTransformer(AliasToBean(typeof(ReportDto)))
.List<ReportDto>();
The ReportDto needs to have a proeprty with the name of each alias "Style", "Color" etc. The output is a list of ReportDto.
I'm not schooled in DDD exactly, but I've always modeled my nouns as types and I'm surprised the report itself is an entity. DDD or not, I wouldn't do that, rather I'd have my reports reflect the results of a query, in which quantity is presumably count(*) or sum(lineItem.quantity) and status is also calculated (perhaps, in the page).
You haven't described your domain, but there is a clue on those column headings that you may be doing a pivot over the data to create LAQty, MTLQty which you'll find hard to do in nHibernate as its designed for OLTP and does not even do UNION last I checked. That said, there is nothing wrong with abusing HQL (Hibernate Query Language) for doing lightweight reporting, as long as you understand you are abusing it.
I see Stefan has done a grand job of describing the syntax for that, so I'll stop there :-)