Skip to content
121 changes: 121 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/NH3565/FixtureByCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System.Data;
using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NHibernate.SqlTypes;
using NUnit.Framework;
using NHibernate.Linq;

namespace NHibernate.Test.NHSpecificTest.NH3565
{
using System.Threading.Tasks;
[TestFixture]
public class ByCodeFixtureAsync : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<Entity>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name, m =>
{
m.Type(NHibernateUtil.AnsiString);
m.Length(10);
});
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

protected override bool AppliesTo(Dialect.Dialect dialect)
{
return base.AppliesTo(dialect)
//Dialects like SQL Server CE, Firebird don't distinguish AnsiString from String
&& Dialect.GetTypeName(new SqlType(DbType.AnsiString)) != Dialect.GetTypeName(new SqlType(DbType.String));
}

protected override void OnSetUp()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var e1 = new Entity {Name = "Bob"};
session.Save(e1);

var e2 = new Entity {Name = "Sally"};
session.Save(e2);

transaction.Commit();
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.CreateQuery("delete from System.Object").ExecuteUpdate();

transaction.Commit();
}
}

[Test]
public async Task ParameterTypeForLikeIsProperlyDetectedAsync()
{
using (var logSpy = new SqlLogSpy())
using (var session = OpenSession())
{
var result = from e in session.Query<Entity>()
where NHibernate.Linq.SqlMethods.Like(e.Name, "Bob")
select e;

Assert.That(await (result.ToListAsync()), Has.Count.EqualTo(1));
Assert.That(logSpy.GetWholeLog(), Does.Contain("Type: AnsiString"));
}
}

[KnownBug("Not fixed yet")]
[Test]
public async Task ParameterTypeForContainsIsProperlyDetectedAsync()
{
using (var logSpy = new SqlLogSpy())
using (var session = OpenSession())
{
var result = from e in session.Query<Entity>()
where e.Name.Contains("Bob")
select e;

Assert.That(await (result.ToListAsync()), Has.Count.EqualTo(1));
Assert.That(logSpy.GetWholeLog(), Does.Contain("Type: AnsiString"));
}
}

[KnownBug("Not fixed yet")]
[Test]
public async Task ParameterTypeForStartsWithIsProperlyDetectedAsync()
{
using (var logSpy = new SqlLogSpy())
using (var session = OpenSession())
{
var result = from e in session.Query<Entity>()
where e.Name.StartsWith("Bob")
select e;

Assert.That(await (result.ToListAsync()), Has.Count.EqualTo(1));
Assert.That(logSpy.GetWholeLog(), Does.Contain("Type: AnsiString"));
}
}
}
}
10 changes: 10 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3565/Entity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace NHibernate.Test.NHSpecificTest.NH3565
{
class Entity
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
}
109 changes: 109 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/NH3565/FixtureByCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System.Data;
using System.Linq;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Mapping.ByCode;
using NHibernate.SqlTypes;
using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.NH3565
{
[TestFixture]
public class ByCodeFixture : TestCaseMappingByCode
{
protected override HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.Class<Entity>(rc =>
{
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
rc.Property(x => x.Name, m =>
{
m.Type(NHibernateUtil.AnsiString);
m.Length(10);
});
});

return mapper.CompileMappingForAllExplicitlyAddedEntities();
}

protected override bool AppliesTo(Dialect.Dialect dialect)
{
return base.AppliesTo(dialect)
//Dialects like SQL Server CE, Firebird don't distinguish AnsiString from String
&& Dialect.GetTypeName(new SqlType(DbType.AnsiString)) != Dialect.GetTypeName(new SqlType(DbType.String));
}

protected override void OnSetUp()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var e1 = new Entity {Name = "Bob"};
session.Save(e1);

var e2 = new Entity {Name = "Sally"};
session.Save(e2);

transaction.Commit();
}
}

protected override void OnTearDown()
{
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
session.CreateQuery("delete from System.Object").ExecuteUpdate();

transaction.Commit();
}
}

[Test]
public void ParameterTypeForLikeIsProperlyDetected()
{
using (var logSpy = new SqlLogSpy())
using (var session = OpenSession())
{
var result = from e in session.Query<Entity>()
where NHibernate.Linq.SqlMethods.Like(e.Name, "Bob")
select e;

Assert.That(result.ToList(), Has.Count.EqualTo(1));
Assert.That(logSpy.GetWholeLog(), Does.Contain("Type: AnsiString"));
}
}

[KnownBug("Not fixed yet")]
[Test]
public void ParameterTypeForContainsIsProperlyDetected()
{
using (var logSpy = new SqlLogSpy())
using (var session = OpenSession())
{
var result = from e in session.Query<Entity>()
where e.Name.Contains("Bob")
select e;

Assert.That(result.ToList(), Has.Count.EqualTo(1));
Assert.That(logSpy.GetWholeLog(), Does.Contain("Type: AnsiString"));
}
}

[KnownBug("Not fixed yet")]
[Test]
public void ParameterTypeForStartsWithIsProperlyDetected()
{
using (var logSpy = new SqlLogSpy())
using (var session = OpenSession())
{
var result = from e in session.Query<Entity>()
where e.Name.StartsWith("Bob")
select e;

Assert.That(result.ToList(), Has.Count.EqualTo(1));
Assert.That(logSpy.GetWholeLog(), Does.Contain("Type: AnsiString"));
}
}
}
}
2 changes: 2 additions & 0 deletions src/NHibernate/Async/IQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
using NHibernate.Transform;
using NHibernate.Type;
using System.Collections.Generic;
using NHibernate.Impl;

namespace NHibernate
{
using System.Threading.Tasks;
using System.Threading;

public partial interface IQuery
{

Expand Down
29 changes: 29 additions & 0 deletions src/NHibernate/IQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,38 @@
using NHibernate.Transform;
using NHibernate.Type;
using System.Collections.Generic;
using NHibernate.Impl;

namespace NHibernate
{
// 6.0 TODO remove
internal static class QueryExtensions
{
/// <summary>
/// Bind a value to a named query parameter
/// </summary>
/// <param name="query">The query</param>
/// <param name="name">The name of the parameter</param>
/// <param name="val">The possibly null parameter value</param>
/// <param name="type">The NHibernate <see cref="IType"/>.</param>
/// <param name="preferMetadataType">If true supplied type is used only if parameter metadata is missing</param>
public static void SetParameter(this IQuery query, string name, object val, IType type, bool preferMetadataType)
{
if (query is AbstractQueryImpl impl)
{
impl.SetParameter(name, val, type, preferMetadataType);
}
else
{
//Let HQL try to process guessed types (hql doesn't support type guessing for NULL)
if (type != null && (preferMetadataType == false || val == null))
query.SetParameter(name, val, type);
else
query.SetParameter(name, val);
}
}
}

/// <summary>
/// An object-oriented representation of a NHibernate query.
/// </summary>
Expand Down
58 changes: 26 additions & 32 deletions src/NHibernate/Impl/AbstractQueryImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,17 +242,33 @@ public IQuery SetParameter(int position, object val, IType type)

public IQuery SetParameter(string name, object val, IType type)
{
if (!parameterMetadata.NamedParameterNames.Contains(name))
{
if (shouldIgnoredUnknownNamedParameters)//just ignore it
return this;
throw new ArgumentException("Parameter " + name + " does not exist as a named parameter in [" + QueryString + "]");
}
else
{
namedParameters[name] = new TypedValue(type, val, false);
return SetParameter(name, val, type, false);
}

//TODO 6.0: Add to IQuery interface
public IQuery SetParameter(string name, object val, IType type, bool preferMetadataType)
{
if (CheckParameterIgnored(name))
return this;

if (type == null || preferMetadataType)
{
type = parameterMetadata.GetNamedParameterExpectedType(name) ?? type ?? ParameterHelper.GuessType(val, session.Factory);
}

namedParameters[name] = new TypedValue(type, val, false);
return this;
}

private bool CheckParameterIgnored(string name)
{
if (parameterMetadata.NamedParameterNames.Contains(name))
return false;

if (shouldIgnoredUnknownNamedParameters) //just ignore it
return true;

throw new ArgumentException("Parameter " + name + " does not exist as a named parameter in [" + QueryString + "]");
}

public IQuery SetParameter<T>(int position, T val)
Expand Down Expand Up @@ -289,29 +305,7 @@ public IQuery SetParameter<T>(string name, T val)

public IQuery SetParameter(string name, object val)
{
if (!parameterMetadata.NamedParameterNames.Contains(name))
{
if (shouldIgnoredUnknownNamedParameters)//just ignore it
return this;
}

if (val == null)
{
IType type = parameterMetadata.GetNamedParameterExpectedType(name);
if (type == null)
{
throw new ArgumentNullException("val",
"A type specific Set(name, val) should be called because the Type can not be guessed from a null value.");
}

SetParameter(name, val, type);
}
else
{
SetParameter(name, val, DetermineType(name, val));
}

return this;
return SetParameter(name, val, null, true);
}

public IQuery SetParameter(int position, object val)
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Linq/DefaultQueryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ private static void SetParameters(IQuery query, IDictionary<string, NamedParamet
}
else
{
query.SetParameter(parameter.Name, parameter.Value);
query.SetParameter(parameter.Name, parameter.Value, parameter.Type, parameter.IsGuessedType);
}
}
}
Expand Down