diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH3426/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH3426/Fixture.cs
new file mode 100644
index 00000000000..a762cbef796
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH3426/Fixture.cs
@@ -0,0 +1,88 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by AsyncGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+using System;
+using System.Linq;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+using NHibernate.Linq;
+
+namespace NHibernate.Test.NHSpecificTest.NH3426
+{
+ using System.Threading.Tasks;
+ [TestFixture]
+ public class FixtureAsync : TestCaseMappingByCode
+ {
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ });
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ private const string id = "9FF2D288-56E6-F349-9CFC-48902132D65B";
+
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ {
+ session.Save(new Entity { Id = Guid.Parse(id), Name = "Name 1" });
+
+ session.Flush();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ {
+ using (var transaction = session.BeginTransaction())
+ {
+ session.Delete("from System.Object");
+
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+ }
+
+ [Test]
+ public async Task SelectGuidToStringAsync()
+ {
+ using (var session = OpenSession())
+ {
+ var list = await (session.Query()
+ .Select(x => new { Id = x.Id.ToString() })
+ .ToListAsync());
+
+ Assert.AreEqual(id.ToUpper(), list[0].Id.ToUpper());
+ }
+ }
+
+ [Test]
+ public async Task WhereGuidToStringAsync()
+ {
+ using (var session = OpenSession())
+ {
+ var list = await (session.Query()
+ .Where(x => x.Id.ToString().ToUpper() == id)
+ .ToListAsync());
+
+ Assert.That(list, Has.Count.EqualTo(1));
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/NH3426/Entity.cs b/src/NHibernate.Test/NHSpecificTest/NH3426/Entity.cs
new file mode 100644
index 00000000000..7edf9b83318
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/NH3426/Entity.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.NH3426
+{
+ public class Entity
+ {
+ public virtual Guid Id { get; set; }
+ public virtual string Name { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/NH3426/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/NH3426/Fixture.cs
new file mode 100644
index 00000000000..06ac532dea1
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/NH3426/Fixture.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Linq;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH3426
+{
+ [TestFixture]
+ public class Fixture : TestCaseMappingByCode
+ {
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Id(x => x.Id);
+ rc.Property(x => x.Name);
+ });
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ private const string id = "9FF2D288-56E6-F349-9CFC-48902132D65B";
+
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ {
+ session.Save(new Entity { Id = Guid.Parse(id), Name = "Name 1" });
+
+ session.Flush();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ {
+ using (var transaction = session.BeginTransaction())
+ {
+ session.Delete("from System.Object");
+
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+ }
+
+ [Test]
+ public void SelectGuidToString()
+ {
+ using (var session = OpenSession())
+ {
+ var list = session.Query()
+ .Select(x => new { Id = x.Id.ToString() })
+ .ToList();
+
+ Assert.AreEqual(id.ToUpper(), list[0].Id.ToUpper());
+ }
+ }
+
+ [Test]
+ public void WhereGuidToString()
+ {
+ using (var session = OpenSession())
+ {
+ var list = session.Query()
+ .Where(x => x.Id.ToString().ToUpper() == id)
+ .ToList();
+
+ Assert.That(list, Has.Count.EqualTo(1));
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/NHibernate.Test.csproj b/src/NHibernate.Test/NHibernate.Test.csproj
index 39642f1886f..f2ff3fce6d8 100644
--- a/src/NHibernate.Test/NHibernate.Test.csproj
+++ b/src/NHibernate.Test/NHibernate.Test.csproj
@@ -55,7 +55,7 @@
-
+
diff --git a/src/NHibernate/Dialect/Dialect.cs b/src/NHibernate/Dialect/Dialect.cs
index f6f37c69280..0733a9dd518 100644
--- a/src/NHibernate/Dialect/Dialect.cs
+++ b/src/NHibernate/Dialect/Dialect.cs
@@ -123,6 +123,7 @@ protected Dialect()
RegisterFunction("bnot", new Function.BitwiseNativeOperation("~", true));
RegisterFunction("str", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as char)"));
+ RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "?1"));
// register hibernate types for default use in scalar sqlquery type auto detection
RegisterHibernateType(DbType.Int64, NHibernateUtil.Int64.Name);
diff --git a/src/NHibernate/Dialect/FirebirdDialect.cs b/src/NHibernate/Dialect/FirebirdDialect.cs
index f79e29eb23e..af32c3e09d5 100644
--- a/src/NHibernate/Dialect/FirebirdDialect.cs
+++ b/src/NHibernate/Dialect/FirebirdDialect.cs
@@ -419,6 +419,7 @@ private void OverrideStandardHQLFunctions()
RegisterFunction("upper", new StandardSafeSQLFunction("upper", NHibernateUtil.String, 1));
RegisterFunction("mod", new StandardSafeSQLFunction("mod", NHibernateUtil.Double, 2));
RegisterFunction("str", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as VARCHAR(255))"));
+ RegisterFunction("strguid", new StandardSQLFunction("uuid_to_char", NHibernateUtil.String));
RegisterFunction("sysdate", new CastedFunction("today", NHibernateUtil.Date));
RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.Date, "cast(?1 as date)"));
// Bitwise operations
diff --git a/src/NHibernate/Dialect/MySQL55Dialect.cs b/src/NHibernate/Dialect/MySQL55Dialect.cs
index fb5de2aa78b..9c47c111221 100644
--- a/src/NHibernate/Dialect/MySQL55Dialect.cs
+++ b/src/NHibernate/Dialect/MySQL55Dialect.cs
@@ -1,5 +1,6 @@
using System.Data;
+using NHibernate.Dialect.Function;
namespace NHibernate.Dialect
{
@@ -8,6 +9,7 @@ public class MySQL55Dialect : MySQL5Dialect
public MySQL55Dialect()
{
RegisterColumnType(DbType.Guid, "CHAR(36)");
+ RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "?1"));
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NHibernate/Dialect/MySQL5Dialect.cs b/src/NHibernate/Dialect/MySQL5Dialect.cs
index 38de3759df3..1dfac2f6f46 100644
--- a/src/NHibernate/Dialect/MySQL5Dialect.cs
+++ b/src/NHibernate/Dialect/MySQL5Dialect.cs
@@ -1,4 +1,5 @@
using System.Data;
+using NHibernate.Dialect.Function;
using NHibernate.SqlCommand;
namespace NHibernate.Dialect
@@ -11,9 +12,12 @@ public MySQL5Dialect()
// My SQL supports precision up to 65, but .Net is limited to 28-29.
RegisterColumnType(DbType.Decimal, 29, "DECIMAL($p, $s)");
RegisterColumnType(DbType.Guid, "BINARY(16)");
+
+ RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "concat(hex(reverse(substr(?1, 1, 4))), '-', hex(reverse(substring(?1, 5, 2))), '-', hex(reverse(substr(?1, 7, 2))), '-', hex(substr(?1, 9, 2)), '-', hex(substr(?1, 11)))"));
}
- protected override void RegisterCastTypes() {
+ protected override void RegisterCastTypes()
+ {
base.RegisterCastTypes();
// MySql 5 also supports DECIMAL as a cast type target
// http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html
diff --git a/src/NHibernate/Dialect/Oracle8iDialect.cs b/src/NHibernate/Dialect/Oracle8iDialect.cs
index c95ed7955bb..4d5d155e02c 100644
--- a/src/NHibernate/Dialect/Oracle8iDialect.cs
+++ b/src/NHibernate/Dialect/Oracle8iDialect.cs
@@ -302,6 +302,7 @@ protected virtual void RegisterFunctions()
RegisterFunction("next_day", new StandardSQLFunction("next_day", NHibernateUtil.Date));
RegisterFunction("str", new StandardSQLFunction("to_char", NHibernateUtil.String));
+ RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "substr(rawtohex(?1), 7, 2) || substr(rawtohex(?1), 5, 2) || substr(rawtohex(?1), 3, 2) || substr(rawtohex(?1), 1, 2) || '-' || substr(rawtohex(?1), 11, 2) || substr(rawtohex(?1), 9, 2) || '-' || substr(rawtohex(?1), 15, 2) || substr(rawtohex(?1), 13, 2) || '-' || substr(rawtohex(?1), 17, 4) || '-' || substr(rawtohex(?1), 21) "));
RegisterFunction("iif", new SQLFunctionTemplate(null, "case when ?1 then ?2 else ?3 end"));
diff --git a/src/NHibernate/Dialect/PostgreSQLDialect.cs b/src/NHibernate/Dialect/PostgreSQLDialect.cs
index a491862cab7..6eebc1a3679 100644
--- a/src/NHibernate/Dialect/PostgreSQLDialect.cs
+++ b/src/NHibernate/Dialect/PostgreSQLDialect.cs
@@ -94,6 +94,8 @@ public PostgreSQLDialect()
// Register the date function, since when used in LINQ select clauses, NH must know the data type.
RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.Date, "cast(?1 as date)"));
+
+ RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "?1::TEXT"));
RegisterKeywords();
}
diff --git a/src/NHibernate/Dialect/SQLiteDialect.cs b/src/NHibernate/Dialect/SQLiteDialect.cs
index e9724cc0dee..dd72bdf5d8a 100644
--- a/src/NHibernate/Dialect/SQLiteDialect.cs
+++ b/src/NHibernate/Dialect/SQLiteDialect.cs
@@ -94,6 +94,8 @@ protected virtual void RegisterFunctions()
// NH-3787: SQLite requires the cast in SQL too for not defaulting to string.
RegisterFunction("transparentcast", new CastFunction());
+
+ RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "substr(hex(?1), 7, 2) || substr(hex(?1), 5, 2) || substr(hex(?1), 3, 2) || substr(hex(?1), 1, 2) || '-' || substr(hex(?1), 11, 2) || substr(hex(?1), 9, 2) || '-' || substr(hex(?1), 15, 2) || substr(hex(?1), 13, 2) || '-' || substr(hex(?1), 17, 4) || '-' || substr(hex(?1), 21) "));
}
#region private static readonly string[] DialectKeywords = { ... }
diff --git a/src/NHibernate/Dialect/SybaseASE15Dialect.cs b/src/NHibernate/Dialect/SybaseASE15Dialect.cs
index bd83454f7f9..1b33b672cdf 100644
--- a/src/NHibernate/Dialect/SybaseASE15Dialect.cs
+++ b/src/NHibernate/Dialect/SybaseASE15Dialect.cs
@@ -104,6 +104,7 @@ public SybaseASE15Dialect()
RegisterFunction("sqrt", new StandardSQLFunction("sqrt", NHibernateUtil.Double));
RegisterFunction("square", new StandardSQLFunction("square"));
RegisterFunction("str", new StandardSQLFunction("str", NHibernateUtil.String));
+ RegisterFunction("strguid", new StandardSQLFunction("str", NHibernateUtil.String));
RegisterFunction("tan", new StandardSQLFunction("tan", NHibernateUtil.Double));
RegisterFunction("trim", new AnsiTrimEmulationFunction("str_replace"));
RegisterFunction("upper", new StandardSQLFunction("upper"));
diff --git a/src/NHibernate/Linq/Functions/StringGenerator.cs b/src/NHibernate/Linq/Functions/StringGenerator.cs
index 149d635c3fe..02cf535951f 100644
--- a/src/NHibernate/Linq/Functions/StringGenerator.cs
+++ b/src/NHibernate/Linq/Functions/StringGenerator.cs
@@ -317,6 +317,8 @@ public IHqlGeneratorForMethod GetMethodGenerator(MethodInfo method)
public class ToStringHqlGeneratorForMethod : IHqlGeneratorForMethod
{
+ private static readonly System.Type _guidType = typeof(Guid);
+
public IEnumerable SupportedMethods
{
get { throw new NotSupportedException(); }
@@ -324,6 +326,11 @@ public IEnumerable SupportedMethods
public HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
+ if (targetObject.Type == _guidType)
+ {
+ return treeBuilder.MethodCall("strguid", visitor.Visit(targetObject).AsExpression());
+ }
+
return treeBuilder.MethodCall("str", visitor.Visit(targetObject).AsExpression());
}
}