Nhibernate - Getting Exception executing SQL Query - c#

I am executing a SQL Query using Nhibernate, below is the code in which I use for this:
public ArrayList getDocumentsForApproval(string ReleaseId)
{
string query = string.Format("SELECT distinct doc.Id, doc.Name as Doc, doc.url as url, suser.Name as Author, ds.name, CONVERT(VARCHAR(11), doc.DateEntered, 101) as DateEntered FROM dbo.Documents doc INNER JOIN DevelopmentSteps ds ON doc.TypeId = ds.Id INNER JOIN DocumentTrackingItems dti ON doc.Id = dti.DocumentId INNER JOIN TrackingItems ti ON dti.ItemStepId = ti.Id INNER JOIN dbo.Releases rl ON ti.ReleaseId = rl.BugTrackerName left outer join (select * from users) as suser on doc.AuthorUserid = suser.Id WHERE doc.DateEntered IS NOT NULL AND doc.DateApproved IS NULL AND rl.ID = '{0}'", ReleaseId);
ISession session = NHibernateHelper.GetCurrentSession();
ArrayList document =(ArrayList) session.CreateSQLQuery(query).List();
return document;
}
The error information I receive is as follows:
**Exception Details:**
NHibernate.QueryException: Return types of SQL query were not specified [SELECT distinct doc.Id, doc.Name as Doc, doc.url as url, suser.Name as Author, ds.name, CONVERT(VARCHAR(11), doc.DateEntered, 101)
What could be the issue? ---- Thanks

You are fundamentally misunderstanding NHibernate. NHibernate is not like the TypeDataSource classes that return you DataSets/DataTables that aren't real business objects.
NHibernate is meant to work with fully owned objects so you would have something similar to
Public Class Document
{
public virtual decimal Id { get; set; }
public virtual string Name { get; set; }
public virtual DateTime DateEntered { get; set; }
... so forth
}
Then you need to create a mapping file either manually or by code generation for raw HBM mappings or use a tool on top of NH to build mappings programmatically with FluentNHibernate or ConfORM.
You need to learn the basics of NHibernate before attempting to query this is a decent introductory post: http://www.fincher.org/tips/Languages/NHibernate.shtml
And then for querying you can use http://www.castleproject.org/ActiveRecord/documentation/v1rc1/usersguide/hql.html for reference.

In most cases you should use entity objects instead of custom queries.
If you really need a custom query, the following example might be useful
public IEnumerable<GeoAreaIdAndCode> ReadAllGssCodes()
{
var query = "select GeoAreaID,Code from GeoAreaAlternativeCode where AlternativeCodeType=" + (int)GeoAreaAlternativeCodeType.GssCode;
var result = Owner.Session.CreateSQLQuery(query)
.AddScalar("GeoAreaID",NHibernateUtil.Int32)
.AddScalar("Code",NHibernateUtil.String)
.SetResultTransformer(Transformers.AliasToBean(typeof (GeoAreaIdAndCode)))
.List<GeoAreaIdAndCode>();
return result;
}
public class GeoAreaIdAndCode
{
public int GeoAreaID { get; set; }
public string Code { get; set; }
}

The secret is to use:
CreateSQLQuery("Your query with alias").AddScalar(...)
In AddScalar you have to define your NH types for output.
See ref here

Related

Need to convert Left join SQL to linq query - help appreciated

Here is my code the issue I have is the less than comparison in the On clause ... Since Linq doesn't allow this .... Migrating down into the where clause wont work as I am comparing one of the fields to null.
Here is the sql query (THE a.UserID= is hardcoded for now)
SELECT A.Policy, A.Comments, A.EventDTTM, A.Status, A.Reason, A.FollowUp
FROM PP_PolicyActivity A
LEFT JOIN PP_PolicyActivity B
ON(A.Policy = B.Policy AND A.EventDTTM < B.EventDTTM)
WHERE A.UserID = 'Ixxxxxx'
AND B.EventDTTM IS NULL AND a.status = 'open - Pending'
order by A.EventDTTM DESC
I need the result set from the above query as an IEnumerable list to populate a view
I'm tasked with rebuilding an old VB ASP NET that has a set of standing production databases behind it ... i don't have the option of changing the db design. I connecting to the server and database and this query was going against a table on that database.. the model also reflects the layout of the actual table.
The problem is with A.EventDTTM < B.EventDTTM - I can't move this to the where clause as I also have to deal with B.EventDTTM IS NULL in the where clause.
I need to retool the query someway so that it is 'linq' friendly
public class PolicyActivityModel
{
public string Policy { get; set; }
public int PolicyID { get; set; }
public string Status { get; set; }
public string Reason { get; set; }
public string Comments { get; set; }
public DateTime EventDTTM { get; set; }
public string UserID { get; set; }
public DateTime FollowUp { get; set; }
}
Company policy prohibits me from showing the connection string.
I am extremely new to Linq, Any help greatly appreciated
thank you
You can use the navigation property after you get the policy from the database.
var policy = DbContext.First(x => x.Id == 1000);
var otherPolicies = policy.ConnectedPolicies.Where(p => ...);
It's weird being a self-join but this is the most direct translation to Linq:
var query = from leftPP in PP_PolicyActivity
join rightPP in PP_PolicyActivity
on new { Policy = leftPP.Policy, EventDTTM = leftPP.EventDTTM }
equals new { Policy = rightPP.Policy, EventDTTM = rightPP.EventDTTM }
into pp from joinedRecords.DefaultIfEmpty()
where leftPP.UserId == 1
&& leftPP.EventDTTM < rightPP.DTTM)
&& rightPP.EventDTTM == null
&& leftPP.status = "open - Pending"
select new
{
leftPP,
rightPP
}
I free typed this, without models or Intellisense, thus there might be some smaller errors.
You could add the order by in that clause, but it's also still an IQUeryable, so I'd leave it.
And then, to get a List of models:
var results = query.OrderByDescending(x => x.EventDTTM).ToList();
The actual join is lines 2,3,4 and 5. It's verbose and "backwards" from SQL, and most importantly uses anonymous types. Accessing indidual properties will look something like:
results[0].leftPP.PolicyId

Performing join using linq query in Entity Framework

I'm trying to select some data from a table in my database using a join in a linq query, but I can't seem to grasp how to save it to the list of DTO's that I would like to return.
I've been looking at this post for directions at using the lambda expression: C# Joins/Where with Linq and Lambda but it seems like that guy is trying to accomplish something slightly different than me; I want to compare the value CPR (from the table Coworkers) and the value CPR (From the table Duties) and select all of those where the Projektname (from the table Duties) are equal to the string projektname.
What I've written so far of the method is this:
public List<CoworkerDTO> GetCoworkers(string projektname)
{
_coworkerlist = new List<CoworkerDTO>();
using (var context = new F17ST2ITS2201608275Entities())
{
var dataset =
from co in context.Coworkers
join du in context.Duties on co.CPR equals du.CPR
where du.Projektname == projektname
select new {Coworkers = co};
foreach (var element in dataset.ToList())
{
_coworkerlist.Add(element);
}
}
return _coworkerlist;
}
The CoworkerDTO looks like this:
class CoWorkerDTO
{
public string Fornavn { get; set; }
public string Efternavn { get; set; }
public int Alder { get; set; }
public string CPR { get; set; }
public decimal AntalTimer { get; set; }
}
The table Coworkers has a column that corresponds to each of the properties above, so I guess my question is how to somehow convert the selection that I get into a list of the CoworkerDTOs.
Sorry for the long post, and if my english is a bit confusing, as it's not my first language.
Thanks in advance :)
You should convert Coworkers entity into CoWorkerDTO. You can do it manually (assume properties have same names and types):
var dtos =
from co in context.Coworkers
join du in context.Duties on co.CPR equals du.CPR
where du.Projektname == projektname
select new CoWorkerDTO {
Fornavn = co.Fornavn,
Efternavn = co.Efternavn,
Alder = co.Alder,
CPR = co.CPR,
AntalTimer = co.AntalTimer
};
return dtos.ToList();
Or you can use something like AutoMapper Queryable Extensions to do that projection automatically:
Mapper.Initialize(cfg =>
cfg.CreateMap<Coworkers, CoWorkerDTO>());
And query with projection will look like
var entities =
from co in context.Coworkers
join du in context.Duties on co.CPR equals du.CPR
where du.Projektname == projektname
select co;
return entities.ProjectTo<CoWorkerDTO>().ToList();

ServiceStack LoadReferences when using SQL Query

Is it possible to Load References when instead of using the code below:
SqlExpression<Customer> q = db.From<Customer>();
q.Join<Customer,CustomerAddress>((cust,address) => cust.Id == address.CustomerId);
List<Customer> dbCustomers = db.LoadSelect(q);
Using this:
public class KpiTotal : IKpiTotal
{
public DateTime Date { get; set; }
public int TeamId { get; set; }
public Team Team { get; set; }
public int AccountId { get; set; }
public Account Account { get; set; }
public double Total { get; set; }
}
var result = dbCon.SelectFmt<KpiTotal>(#"select convert(date, t.TransactionDate) [Date], tm.TeamId,a.AccountNumber, count(distinct(t.RequisitionNumber)) Total
from task.tblTransactions t
inner join task.tblRequisitions r on r.RequisitionNumber = t.RequisitionNumber
inner join task.tblAccounts a on a.AccountNumber = r.AccountNumber
inner join Team tm on tm.DivisionId = a.DivisionId
where t.TransactionTypeNumber = 201 and a.IsActive = 1
and t.TransactionDate between {0} and {1}
group by convert(date, t.TransactionDate), tm.TeamName, a.AccountName
order by 1,2 desc", dateRange.Start, dateRange.End);
Because my result object (KpiTotal) has references to two child tables, and I would like to automatic load the references, instead of getting it with a foreach block.
I'm assuming you want to load in Team and Account from the above query. The LoadSelect method sniffs the POCO model and generates a query that pulls back all related DB records based on the foreign key relationships to the core object you're querying. It generates a query similar to this for each referenced / joined POCO (very pseudo-coded):
SELECT * FROM Team /* Related POCO */
WHERE Team.Id IN (SELECT TeamId FROM [original query with WHERE clase])
Basically, it does a single query to bring back all Teamss or Accounts.
With ServiceStack.OrmLite v4.0.40, there is now a new Merge extension method that will stitch together object references based in a more manual process.
In your case, you can query your KpiTotal results, then run just two separate queries to fetch back Team and Account lists, then merge them in. Basically:
var result = dbCon.SelectFmt<KpiTotal>(/* gnarly SQL */);
var teams = dbCon.Select(/* get all relevant teams */);
var accounts = dbCon.Select(/* get all relevant accounts */);
result.Merge(teams);
result.Merge(accounts);
Debug.WriteLine(result.Dump()); // Output to console / debug window, whatever

Understanding the basic for Linq queries

Suppose I have a Table in my database named Table1. I have 3 columns in Table1 named
FirstName
SurName
DOB
In sql I would simply do select * from Table1 and it'll display everything from that particular table. However what I am trying to understand is how would I select all the values from this table using Linq in C#. Table1 is in the database and the front-end is being developed using ASP.NET and C# I just can't seem to get my head around this. My knowledge on linq is very little so do excuse me if I'm making an obvious mistake
See below links for an intro to linq
What is Linq and what does it do?
http://weblogs.asp.net/scottgu/using-linq-to-sql-part-1
Linq provides a mean of querying data, but you still need to provide a means of Linq accessing that data - be it through Linq2Sql classes, ADO, Entity Framework, etc.
I'm a fan of Entity Framework (EF) where you set up objects that represent your data, and use a context to populate those objects.
it could look something like this:
public class Table1
{
public string FirstName { get; set; }
public string SurName { get; set; }
public DateTime DOB { get; set; }
}
public class Table1Repository
{
private readonly MyEntities _context;
public Table1Repository()
{
this._context = new MyEntities();
}
public IQueryable<Table1> Get()
{
return this._context.Table1; // in effect your "Select * from table1"
}
public IQueryable<Table1> GetById(DateTime dob)
{
return this._context.Table1.Where(w => w.DOB == dob); // pulls records with a dob matching param - using lambda here but there is also "query expression syntax" which looks more like sql
}
}
Note that you're performing linq queries on the context that represents the data, not the database itself. Linq is very powerful, but you need to provide it a means of accessing data. Even if that data is as xml, a file, a database, whatever!
In Linq2Sql you would select all field quite simply by
Starting with a datacontext:
var db = new YourDataContext()
And after that you can do things like
var myData = from row
in db.table1
select row
As you indicate yourself, your knowledge is too limited. Check out this series about L2S:
http://weblogs.asp.net/scottgu/using-linq-to-sql-part-1
Since you are using EF6 you can read your table using LinqToEntity.
public ObservableCollection<Table1> ReadTable1()
{
using (YourDBContext dc = new YourDBContext())
{
var data = (from x in dc.Table1
select x);
return new ObservableCollection<Table1>(data);
}
}

How to select only a few columns in my NHibernate query?

I have a one class to one table mapping; unfortunately this table has 110+ columns, and queries take a long time process, especially when most of the time I only want to view <10 columns.
My problem is that the queries are dynamically generated based on what the user wants to look at. I can't really create different mappings with different columns because there would be a very large number of combinations. I'm using the criteria API to generate the queries. Can I also use this to only select the columns the user wants? Or some other method?
Thanks
Easy to do with LINQ (assuming you're using NHibernate 3.0 or later):
var products = from p in Session.Query<Product>()
where // ...some query (snip)
select new
{
Name = p.ProductName,
Description = p.ShortDesc,
Price = p.Price,
Units = p.Quantity
};
Also, if you're using HQL, you can just select the columns you need similar to using T-SQL, but use a Transformer to get a strongly typed object back:
First create a class with your narrowed down columns:
public class ProductReport
{
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int Units { get; set; }
}
Then your query:
string hql = "select p.ProductName as Name, p.ShortDesc as Description ...(snip) " +
"from Product p " +
"where ...some query (snip)";
IQuery query = Session.CreateQuery(hql)
.SetResultTransformer(Transformers.AliasToBean<ProductReport>());
IList<ProductReport> products = query.List<ProductReport>();
Just sure make the aliases in your query (as Name, as Description etc.) match the property names in your class.
In addition to the example Tim gave you can do something like this:
IList selection =
session.QueryOver<Cat>()
.Select(
c => c.Name,
c => c.Age)
.List<object[]>();
Above example was taken from: http://nhforge.org/blogs/nhibernate/archive/2009/12/17/queryover-in-nh-3-0.aspx
Use a ProjectionList to select the columns you want. See here for the examples.

Categories

Resources