Fluent NHibernate: Custom condition (WHERE clause) on get, update and delete - fluent-nhibernate

I have a table that contains information from many customers
ID | employeename | customerId
------------------------------
1 | employee1 | 188
2 | employee2 | 188
3 | employee3 | 177
Now I would like to get only those employees, whose customerId is 188. How do I map this with Fluent NHibernate so, that on update and delete there would also be WHERE customerId = 188 ?
Current Mapping is something like:
Id(x => x.Id);
Map(x => x.Name).Column("employeename");
Map(x => x.CustomerId).Column("customerId");
Adding Where("customerId = 188") only results custom where clause in SELECT. I would need following UPDATE-clause to happen on saveorupdate.
UPDATE employees SET employeename="employ" WHERE ID = 2 AND customerId = 188;

You are thinking wrong with this SQL mind in your head.
1) Add HasMany( x => x.Employees ).Inverse().AsSet(); in your Customer class.
2) Add References( x=> x.Customer ); in your Employee class.
This is called bidirectional mapping.
Look here: http://www.progware.org/Blog/post/NHibernate-inverse3dtrue-and-cascade3dsave-update-demo.aspx
The idea is that you create your objects and you assign values to them. After that NHibernate executes SQL statements if you have proper mapping files. Dont write your sql queries and then forcing NHibernate to generate exactly the same ones. Instead write your mappings and see what SQL NHibernate generates and try to optimize it.
PS: Dont forget to add the cascade...

Related

How can I order a query by a related field?

Using Yii 1.1.15 assume I have a model:
State(id,name) ----- 1<>N ----- City(id,state_id,name)
#the only relevant field in each is `name`, having City the
#corresponding FK field to State.
And want to query cities sorted (asc) by State Name, and then (asc) by City name.
City::model()->with('state')->findAll(array('order' => 'name ASC'));
How do I alter the sort criteria to consider the state name?
(footnote: in other frameworks like Python/Django I'd do City.objects.select_related('state').order_by('state__name', 'name') - i.e. many frameworks have support for a nested ordering - does Yii have as well?)
USe this
City::model()->with(array('with'=>array(
'state'=>array(
'alias'=>'v',
'order'=>'t.name ASC',
)
))->findAll();

Fluent nHibernate Mapping with Ternary Mapping Table

Have a legacy database with mapping table structures like the following. I am trying to figure out how to fluently map this type of relationship.
There are multiple parent tables that use a mapping table to store notes.
The parent tables look like the following:
P1 Table
ID iSomething
P2 Table
ID iSomethingElse
There is a mapping table that will take a parent table and map it to a note table.
Mapping Table
ID i_RecordUniqueID
ID i_NoteID
ID i_RecordID
The column i_RecordID contains a numeric value indicating which parent table the i_RecordUniqueID value came from. The mapping table only has those three columns and is a ternary primary key.
Here is the note table:
Note Table
ID i_NoteID
The query to find table P1's notes is as follows:
Select n.*
from P1 p
inner join Mapping m on p.iSomething = m.i_RecordUniqueID and m.i_RecordID = 1
inner join Note n on m.i_NoteID = n.i_NoteID
The query to find table P2's notes is as follows:
Select n.*
from P2 p
inner join Mapping m on p.iSomething = m.i_RecordUniqueID and m.i_RecordID = 2
inner join Note n on m.i_NoteID = n.i_NoteID
In my Parent tables mapping file, I have an association like the below. I don't know how to add the i_RecordID constraint.
HasManyToMany<Note>(x => x.Notes)
.Table("Mapping")
.ParentKeyColumn("i_RecordUniqueID")
.ChildKeyColumn("i_NoteID")
.Cascade.All();
FluentNHibernatew does not yet support ManyToAny mapping. you could map it for readonly access
// P1Map()
HasManyToMany(x => x.Notes)
.Table("Mapping")
.ParentKeyColumn("i_RecordUniqueID")
.Where("i_RecordID == 1")
.ChildKeyColumn("i_NoteID")
.Cascade.All();
// P2Map()
HasManyToMany(x => x.Notes)
.Table("Mapping")
.ParentKeyColumn("i_RecordUniqueID")
.Where("i_RecordID == 2")
.ChildKeyColumn("i_NoteID")
.Cascade.All();
or you have to create a component
ICollection<TableToNote> Notes;
public TableToNoteMap()
{
ReferencesAny(x => x.Parent).IdentityColumn("i_RecordUniqueID").MetaTypeColumn("i_RecordID")...;
References(x => x.Note);
}

NHibernate Linking Table with Data

SQL 2008 | .NET 4.0 | NHibernate 3.1 | NHibernate.Castle 3.1 | Castle.Core 2.5.2
So I have a linking table with metadata, like the author of this question NHibernate Mapping a Many to Many with Data on Join Table
Initially, I mapped just like the answer to this question as it seemed the most parsimonious way to handle it. However, after turning on show_sql and observing what was going on, the ID lookups ended up yielding N+1 queries where N is the number of associations.
Observe this example database that is analogous to my actual data, defined in sql-like syntax
CREATE TABLE [User]
(
Id int PRIMARY KEY
)
CREATE TABLE UserPref
(
Id int PRIMARY KEY,
Name varchar(32)
)
CREATE TABLE UserPrefAssociation
(
UserId int,
PrefId int,
Value varchar(32)
)
I hacked the following code together with this User one-to-many object mapping IList<UserPrefAssociation> Preferences { get; set; }
public IDictionary<string, string> GeneratePrefDict()
{
return Preferences
.ToDictionary(i => i.UserPref.Name, i => i.Value);
}
Sure, this works great, but as mentioned before, each i.UserPref.Name, is an additional query to SQL.
After playing in SQL, I have found the query that accomplishes what I want. My question then becomes how can I do this with NHibernate?
SELECT UserPref.Name, UserPrefAssociation.Value
FROM [User]
INNER JOIN UserPrefAssociation ON [User].Id = UserPrefAssociation.UserId
INNER JOIN UserPref ON UserPrefAssociation.UserPrefId = UserPref.Id
WHERE [User].Id = 1
~~~~SOLVED~~~~~
using NHibernate.Linq;
...
public IDictionary<string, string> GeneratePrefDict(ISession s)
{
return
(from entry in s.Query<User_UserPref>()
where entry.User == this
select new
{
key = entry.UserPref.Name,
value = entry.Value
})
.ToDictionary(i => i.key, i => i.value);
}
Generates this SQL
NHibernate: select userpref1_.Name as col_0_0_, user_userp0_.Value as col_1_0_ f
rom User_UserPref user_userp0_ left outer join UserPref userpref1_ on user_userp
0_.UserPrefId=userpref1_.Id where user_userp0_.UserId=#p0;#p0 = 1 [Type: Int32 (
0)]
Which is better than N+1 queries, and solves my issue.
I think you can achieve what you are wanting with Futures and QueryOver. Take a look at the following article:
Fighting cartesian product (x-join) when using NHibernate 3.0.0
If you can't visualize how to accomplish what you need from the above I can tailor that example more to your needs.

PostgreSQL: How to optimize this query

I am developing a small application in C++ and using PostgreSQL as back-end database. Along with other tables in my database in have a "projects" table. Based on each primary key of this table a new table is dynamically added in my Database.
Example:
Suppose the projects table contains following 3 rows:
--------------------------------
| Id |Other Columns Goes here |
--------------------------------
| 1 | |
--------------------------------
| 2 | |
--------------------------------
| 3 | |
--------------------------------
So in this case i also have following three more table
Table1, Table2, Table3
Now you might notice that the table names are generated by appending projects.Id at the end of fixed string i.e "Table".
It might also be possible that for some projects no table is generated.
Example:
Suppose the projects table contains following 3 rows:
--------------------------------
| Id |Other Columns Goes here |
--------------------------------
| 1 | |
--------------------------------
| 2 | |
--------------------------------
| 3 | |
--------------------------------
So in this i might found only following two tables in my database:
Table1, Table3
Now i simply need to get all the valid projects. For this currently i am using following algo:
//part1
SELECT * FROM Projects Table
get the projects info one by one from the results of above query and store them in new instance of my Custom Class Project
Store the above instance in some contianer e.g Vector say vProjects
//part 2
For each Project p in vProject
if (TableExist(p.Id))
Store p in a new container say vValidatedProjects
Note: The TableExist() method execute the following query:
SELECT COUNT(*) FROM pg_tables WHERE tablename = 'Table"+ p.Id + "'"
Now every thing is working fine as expected but !!! the program executes very slow just because of the second part of above algo, if we have one thousand projects the TableExist() method is also called thousand time and each time this method is called a new query is executed which slow downs the program :(
The solution in my mind is some such thing
//part1
SELECT * FROM Projects Table
WHERE a table exist angainst projets.Id
get only those projects info for whom a dynamic table exist. From the results of above query and store them in new instance of my Custom Class Project
Store the above instance in some contianer e.g Vector say vProjects.
Now in this way only one query did the job for us rather than N+1 Queries (Where N is no of rows in Projects Table)
But i don't know how do i write such a query that returns the above results. Please help me in acheiving this.
Changing the design would be the best solution.
If that is not an option, then you could change the second part:
//part 2
For each Project p in vProject
if (TableExist(p.Id))
Store p in a new container say vValidatedProjects
Note: The TableExist() method execute the following query:
SELECT COUNT(*) FROM pg_tables WHERE tablename = 'Table"+ p.Id + "'"
by, first adding a new boolean column in projects table (lets name it projects.TableExists )
Then, run your current TableExist() function one and populate that column. In addition, chnage the code that creates table for a project, to also update that column and the code that deletes a table to also update the column accordingly.
Then your second part would be:
//part 2
For each Project p in vProject
if (p.TableExists)
Store p in a new container say vValidatedProjects
Note: The TableExist() method will not be used any more
I would rather have one table with project_id in it and do all selects with where project_id = .... That would result in better table statistics and the table optimizer will make a better job.

SQL and Entityframework, can't get the result I want

I have 2 questions, one about SQL and one about Entity Framework:
I have a table "UserSet" with all information about the user; and I have the table "FriendRequests", that handles UserID and FriendID information. My current user is "rugardini". I need to list the Friends requests. So, I did a query like this only for testing purposes:
select fq.FriendID, u.Nickname from
FriendRequestsSet as fq, UserSet as u
where fq.UserID=16
But my result is like this:
| FriendID | Nickname |
------------------------
| 17 |rugardini |
| 17 | Teste |
== edited ====================
Now I realize my query should be:
SELECT u.ID, u.Nickname
FROM UserSet as u, FriendRequestsSet as f
WHERE u.ID=f.FriendID
ORDER BY u.ID
I'm getting the right result ^^ I still need to know how to "translate" it to EF4.1?
Rubia in Linq its almost similar
from u in USerSet
join f in FriendRequestsSet
on u.ID=f.FriendID
ORDERBY u.ID
select new {u.ID,u.Nickname}
for using this query you would like to use different column from each table to create a new view (as we do in sqlserver). We need to create a Viewmodel in MVC that will represent columns
public class FriendRequest
{
int col1{get;set;}
int col2{get;set;}
//Here comes the Column You Want To Consider For your View Model
}
var list=from u in USerSet
join f in FriendRequestsSet
on u.ID=f.FriendID
ORDERBY u.ID
select new FriendResquest{Col1=u.ID,col2=u.Nickname}
//Here by map your columns as declared in your view model