NHibernate 3 - How to perform a LIKE on an id/numeric/int - queryover

Whilst SQL Server is perfectly comfortable doing:
where Id like '45%'
(id being an int), NH will complain as it will still try to send the compare value into sql as a SqlParameter of type int when doing:
q.WhereRestrictionOn(cl => cl.CompanyId).IsLike(companyIdFilter)
So how to get round it with the new QueryOver API?

After some digging around and and trial and error, this does the trick:
q.Where(Expression.Like(
Projections.Cast(
NHibernateUtil.String,
Projections.Property<ChangeLog>(cl => cl.CompanyId)),
companyIdFilter.Value.ToString(),
MatchMode.Start
));

Related

SqlAlchemy SQLServer and the date() function

I have this code in sqlAlchemy:
result = session.query(FXHoliday).where(
and_(
FXHoliday.country_region_code == country,
func.DATE(FXHoliday.event_date) == when.date()
)
).all()
Now this functions works like charm but in sqlserver :( ...
The above function is translate in
SELECT [FX_HOLIDAY].countryorregion AS [FX_HOLIDAY_countryorregion],
[FX_HOLIDAY].holidayname AS [FX_HOLIDAY_holidayname],
[FX_HOLIDAY].normalizeholidayname AS [FX_HOLIDAY_normalizeholidayname],
[FX_HOLIDAY].ispaidtimeoff AS [FX_HOLIDAY_ispaidtimeoff],
[FX_HOLIDAY].countryregioncode AS [FX_HOLIDAY_countryregioncode],
[FX_HOLIDAY].date AS [FX_HOLIDAY_date]
FROM [FX_HOLIDAY]
WHERE [FX_HOLIDAY].countryregioncode = ?
AND
DATE([FX_HOLIDAY].date) = ?
And it is correct, however there is no DATE() in sqlserver.
I can fix the problem making the date column varchar, so that I can use:
FXHoliday.event_date == when.strftime("%Y-%m-%d")
But it's REALLY an UGLY solution.
I was wondering if some developer found a better and more elegant solution ....
I believe you're trying to make sure that a datetime object (what I'm assuming when is) is interpreted as a date.
There's an sqlalchemy function for this:
from sqlalchemy import func
result = session.query(FXHoliday).where(
and_(
FXHoliday.country_region_code == country,
FXHoliday.event_date == func.date(when)
)
).all()
Though you're using func.DATE for the first part, just use it for both.
UPDATE: I think you're trying to cast a pre-existing DATE column as a DATE, but what you really want to cast is the pythonic object.

Entity Framework 6 and Geography data STContains

I've included Microsoft.SqlServer.Types to enable the geography and geometry types in Entity Framework, but I don't see any functions equivalent to STContains().
I need to make a query to retrieve the geography that contains a point
In SQL I wrote like this:
SELECT adm1code, adm1name
FROM Adm2GeoBoundaries
WHERE Coords.STContains(geography::Parse('POINT(-121.703796 46.893985)'));
in LINQ I expect to have something like
using (GeoEntities db = new GeoEntities ())
{
DbGeography location = DbGeography.FromText("POINT(-121.703796 46.893985)");
var admin = from a in db.Adm2GeoBoundaries
where a.Coords.STContains(location)
select a;
}
but a.Coords.STContains(location) throws an error
STContains method doesn't exist
According to the source code for EF6 Source Code, the STContains seems to be implemented as Contains in EF6.
https://github.com/aspnet/EntityFramework6/blob/master/src/EntityFramework.SqlServer/SqlSpatialServices.cs
Looking at the SqlTypesAssembly.cs you should be able see it should invoke the STContains method.

Decrease value of a field using Spring JDBC template

I am trying to decrease the value of a field in DB2 Table using Spring JDBC template.Below is my code
String sql= "UPDATE XYZ SET CURR_COUNT = CURR_COUNT-1 WHERE COMPANY_CODE =?";
int rowsUpdated = jdbcTemplate.update(sql, new Object[] {compCode});
This gives me error "**PreparedStatementCallback; bad SQL grammar**"
If I am not wrong the error is because of this **"CURR_COUNT = CURR_COUNT-1"** as program dont have value of CURR_COUNT. Can anybody suggest me a solution for this.
You could take value from database via SELECT to variable (int or long), decrement it in java, and then save new value in UPDATE query.

Dapper: Not able to parse floats (Error parsing column)

I am retrieving data from SQL Server from a StoredProcedure using Dapper and I'm getting error
Specified cast is not valid.
and details:
Error parsing column 4 (SubTotal=0.00 - Decimal)
On SQL Server side the column SubTotal is decimal(18, 2) NULLABLE and on .NET side it's decimal?. The data being retrieved is 0.00.
I checked this answer: Dapper,decimal to double? Error parsing column X
As per answer, I replaced
il.Emit(OpCodes.Ldtoken, unboxType);
with
il.Emit(OpCodes.Ldtoken, Nullable.GetUnderlyingType(unboxType) ?? unboxType);
on line 2360 and still getting the same error.
Anyone has any ideas about this? Thanks.
Update:
I tried making column non-nullable. Also tried changing column to float (on SQL Server) and double (on .NET side). None of these worked and I was getting the same error. Then I changed column to int and now code works fine. However, I'm working with monetary values and would like to use floating point numbers. Will investigate further...
I'm executing a stored procedure as follows
var transaction = this.db.Query<PaymentTransactions>("usp_PaymentTransactionsGetSingleIfPaid", new { registrationId }, commandType: CommandType.StoredProcedure);
The relevant part of the stored procedure that returns information is below.
SELECT * FROM PaymentTransactions WHERE RegistrationId = #registrationId AND TransactionStatus = 'SUCCESS';
UPDATE 2:
Dapper is working fine. Maybe there was something wrong with my dev environment. All it took was VS restart.
Don't laugh, but I had this exact same problem with Dapper in an ASP.NET MVC project and the solution as in the comment from #erdinger worked also for me:
Close Visual Studio
Start Visual Studio again
The problem was fixed this way...
Seems like this is not Dapper specific, as I just verified the below snippet works as expected.
Try enumerating your column names explictly (instead of select *) so that the procedure returns exactly what should be mapped to PaymentTransactions. Its possible there is another non-decimal column that is misnamed?
This is using Dapper v1.13 on .Net45:
Procedure:
create procedure dbo.Test
as
select [SubTotal] = cast('0.01' as decimal(18,2))
union all
select null;
Linqpad:
void Main()
{
using (IDbConnection cnn = GetOpenConnection())
{
var users = cnn.Query<Sale>("yak.dbo.test", new { }, commandType: CommandType.StoredProcedure);
users.Dump();
}
}
public static readonly string connectionString = "Data Source=.;Initial Catalog=tempdb;Integrated Security=True";
public static IDbConnection GetOpenConnection()
{
var connection = new SqlConnection(connectionString);
connection.Open();
return connection;
}
public class Sale
{
public decimal? SubTotal;
}
Returns:

Update uses previously autogenerated ID on Oracle

We're having a strange problem in Oracle. I'll sketch some (simplified) context first:
Consider this mapping to an Entity:
public EntityMap()
{
Table("EntityTable");
Id(x => x.Id)
.Column("entityID")
.GeneratedBy.Native("ENTITYID").UnsavedValue(0);
Map(x => x.SomeBoolean).Column("SomeBoolean");
}
and this code:
var entity = new Entity();
using (var transaction = new TransactionScope(TransactionScopeOption.Required))
{
Session.Save(entity);
transaction.Complete();
}
//A lot of code
if(someCondition)
{
using (var transaction = new TransactionScope(TransactionScopeOption.Required))
{
enitity.SomeBoolean = true;
Session.Update(entity);
transaction.Complete();
}
}
This code is called a few times. The first time it generates the following queries:
select ENTITYID.nextval from dual
INSERT INTO Entity
(SomeBoolean, EntityID)
VALUES (0, 1216)
UPDATE Entity
SET SomeBoolean = 1
WHERE EntityID = 1216
The second time it is called these queries are generated (someCondition is false)
select ENTITYID.nextval from dual
INSERT INTO Entity
(SomeBoolean, EntityID)
VALUES (0, 1217)
And now the trouble begins. From now on, each insert will use the correct autoincremented value, but the update will always use 1217
select ENTITYID.nextval from dual
INSERT INTO Entity
(SomeBoolean, EntityID)
VALUES (0, 1218)
UPDATE Entity
SET SomeBoolean = 1
WHERE EntityID = 1217
And of course, this is not what we want to happen. If I inspect the value of the Id while debugging, it contains the correct autoincremented value. Somehow, deep in the bowels of NHibernate, the incorrect is is assigned to the WHERE clause...
The strange part is that this only happens on Oracle. If I switch NHibernate to MsSql, everything works like a charm.
So I found out what happened. NHibernate changed it's default connection release mode between versions 1.x and 2.x. Instead of closing the connection when the session is Disposed, the connections is now closed after each transaction. However, we were manually coordinating our transactions which apparently caused troubles in Oracle.
This question has some extra information and this entry in the NHibernate documentation also clarifies how the connections are handeled:
As of NHibernate, if your application manages transactions through .NET APIs such as System.Transactions library, ConnectionReleaseMode.AfterTransaction may cause NHibernate to open and close several connections during one transaction, leading to unnecessary overhead and transaction promotion from local to distributed. Specifying ConnectionReleaseMode.OnClose will revert to the legacy behavior and prevent this problem from occuring.
This blog post is what got me looking in the right direction.

Resources