nhibernate group by select column based on restrictions - nhibernate

I have what seems to be a rather simple problem, that I cannot figure out right now.
I have a table like so:
id | type | value | comment | date
1 1 22 test dec 2nd
2 1 23 foo dec 4th
3 2 2 bar dec 1st
Based on the model
class MyClass
public virtual long Id { get; set;}
public virtual long Type { get; set;}
public virtual long Value { get; set;}
public virtual string comment { get; set;}
public virtual DateTime Date { get; set;}
I need to group by type and select the row having the most recent date.
(That is, fetch rows with ID 2 and ID 3).
Can someone provide a Criteria with explanation of how to do this ?

two roundtrips, 1 to get the type/date of the desired rows and 1 combined to get each row. FutureValue<> will combine each Query in the loop to one roundtrip and the select converts the FutureValues to the actual values.
class TypeDate
{
public long Type { get; set; }
public DateTime Date { get; set; }
}
var groups = session.CreateCriteria<MyClass>()
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("Type"), "Type")
.Add(Projections.Max("Date"), "Date"))
.SetResultTransForm(Transformers.AliasToBean<TypeDate>());
.List<TypeDate>();
List<IFutureValue<MyClass>> futures = new List<IFutureValue<MyClass>>(groups.Count);
foreach (var group in groups)
{
futures.Add(session.CreateCriteria<MyClass>()
.Add(Restrictions.Eq("Type", group.Type))
.Add(Restrictions.Eq("Date", group.Date))
.FutureValue<MyClass>());
}
IEnumerable<MyClass> results = futures.Select(future => future.Value).ToList();

Related

How can I join two tables and get a count of the number of times the joins match if there might not be a corresponding entry in one table?

In SQLite I have two tables:
public class DeckSource {
[PrimaryKey, NotNull]
public string DeckGuid { get; set; }
public string Type { get; set; }
public string Name { get; set; }
}
and
public class Deck {
[PrimaryKey, NotNull]
public long IdEs { get; set; }
public string DeckGuid { get; set; }
public string Type { get; set; }
public string Name { get; set; }
}
My application has an add button which when pressed takes the data from a row in DeckSource and populates Deck. So for every DeckSource there can be multiple decks. I would like to get a report from DeckSource that shows how many times each Deck has been added to Deck.
If the DeckSource table looks like this:
DeckGuid Name
abc abcrow
def deform
ghi ghirow
and Deck looks like this:
IdEs DeckGuid Name
1 abc abcrow
2 abc abcrow
3 abc abcrow
4 chi ghirow
How can I create a report that shows:
DeckGuid Name Qty
abc abcrow 3
def defrow 0
ghi ghirow 1
Have you tried this?
select decksource.deckguid,decksource.name,count(*)
from decksource
left join deck
on decksource.deckguid = deck.deckguid
group by decksource.deckguid

MVC base model properties set default values for new record creation

I have a base model that has some common properties for several different forms.
public class BaseForm
{
public int Id { get; set; }
public int SubId { get; set; }
...several more common properties...
}
I then have more specific models for the individual forms.
public class InfoForm : BaseForm
{
public string Information { get; set; }
public string Commands { get; set; }
}
public class WhatForm: BaseForm
{
public string WhatHappens { get; set; }
public string Behavior { get; set; }
}
Now when updating these models everything works great as the BaseForm.Id and BaseForm.SubId are populated by the existing record.
My lack of knowledge comes when creating a NEW record. The BaseForm.Id and BaseForm.SubId are predictable but different for each form.
For InfoForm they would be
Record one..
BaseForm.Id = 1
BaseForm.SubId = 1
Record two..
BaseForm.Id = 2
BaseForm.SubId = 1
Record three..
BaseForm.Id = 3
BaseForm.SubId = 1
//Since Id is auto increment I assume it can be left blank for db
and WhatForm they would be
Record one..
BaseForm.Id = 1
BaseForm.SubId = 2
Record two..
BaseForm.Id = 2
BaseForm.SubId = 2
Record three..
BaseForm.Id = 3
BaseForm.SubId = 2
//Since Id is auto increment I assume it can be left blank for db
I was aiming to have a single controller action and every form points to it but if I have to have a different controller action to set specific values to id and subid then so be it.
So my question is there a way to pre-populate these values or do I have to do it in the controller action?
Just use the constructor of your subclasses:
public class InfoForm : BaseForm
{
public InfoForm()
{
SubId = 1;
}
...
}
And, yes, you shouldn't mess with Id. Entity Framework will back-fill it with the auto id from the database, after saving.

RavendB: Select and GroupBy - cannot use Map/Reduce Index

I've got following data structure.
public class Usage
{
public string Id { get; set;}
public string CatalogNumber { get; set;}
public string ProductDescription { get; set;}
public string ProductType { get; set;}
public DateTime DeliveryDate { get; set;}
public int AmountSold { get; set;}
}
I would like to have the result grouped by {CatalogNumber}, {ProductDescription}, {ProductType} within a specific {DeliveryDate}
ie. I'd like to query the total amount sold for a specific product within 2013-01-01 to 2013-04-04.
Expected result:
{
{
CatalogNumer: 12345
ProductDescription: Product1
ProductType: TV
TotalAmountSold: 125
}
{
CatalogNumer: 8797
ProductDescription: Product2
ProductType: Fridge
TotalAmountSold: 13
}
}
Unfortunately I cannot use a Map/Reduce index because there's no way to pass parameters to the index.
Any ideas?
You don't need to pass parameters to the index. First create a map/reduce index grouped by DeliveryDate. Then you query that index with the desired date range.

PetaPoco returning incorrect ID

I have the following model and methods:
[PetaPoco.TableName("TestStep")]
[PetaPoco.PrimaryKey("ID")]
public class TestStep
{
public int ID { get; set; }
public int ParentID { get; set; }
public string Name { get; set; }
public string Details { get; set; }
}
public IEnumerable<TestStep> GetById(int ID)
{
var db = new PetaPoco.Database("TestProcedureDB");
return db.Query<TestStep>(#"SELECT * FROM TESTSTEP TS
INNER JOIN TESTSTEPLINK L ON L.STEPID = TS.ID
WHERE L.TESTID = #0", ID);
}
When the POCO is populated, the ID property value is that of the ID column in the TESTSTEPLINK table. If I change the query to return SELECT TS.* then all is ok. Is this a bug or am I missing something?
PetaPoco will go through all your return columns and map them.
First it will map Id from the table TESTSTEP, then it finds Id again and so it overrides the previously set value.
If you are doing a join like this and only want specific information, you should either only specify the columns you want to return (otherwise you are bringing back more data than needed which is a performance issue)
or do as you did to fix it by using TS.* to ensure only the columns from the first table are mapped.

NHibernate - query specific columns and return distinct records?

I am new to NH.
I have a table in a legacy DB that looks like this:
Id,
CompanyId,
Description,
[LOADS of other columns here]
I would like to return a DISTINCT set of data using NHibernate, selecting only specific columns and using a WHERE statement. The SQL would looks something like this:
SELECT DISTINCT
[table_name].CompanyId,
[table_name].Description
FROM
[table_name]
WHERE
[table_name].CompanyId = 2
Having googled this I came up with:
ProjectionList projections = Projections.ProjectionList();
projections.Add(Projections.Property("CompanyId"), "CompanyId");
projections.Add(Projections.Property("Name"), "SomeName");
var companyDto = session.QueryOver<Company>()
.Where(x => x.CompanyId == 2)
.Select(projections)
.TransformUsing(Transformers.AliasToBean<CompanyDto>())
.List<CompanyDto>();
if (companyDto != null)
Console.WriteLine(string.Format("{0}, {1}", companyDto.CompanyId, companyDto.SomeName));
Where the DTO is:
public class CompanyDto
{
public int CompanyId { get; set; }
public string SomeName { get; set; }
}
And the entity is:
public class Company
{
public virtual int Id { get; private set; }
public virtual int CompanyId { get; set; }
public virtual string Name { get; set; }
}
This does not bring back disinct records. I know that normally I would have to use a different transform (DistinctRootEntity) but I cannot use two transforms. How can I combine all of the things I want, into a single call? It must be possible, its basic SQL ....
I need to:
not use HQL
not bring back all columns for the record
not bring back duplicate rows
there is a Projection for this
var projections = Projections.Distinct(Projections.ProjectionList()
.Add(Projections.Property("CompanyId").As("CompanyId"))
.Add(Projections.Property("Name").As("SomeName"));