diff --git a/src/NHibernate.Test.VisualBasic/Issues/GH3716/Entity.vb b/src/NHibernate.Test.VisualBasic/Issues/GH3716/Entity.vb new file mode 100644 index 00000000000..4fcdb0841e5 --- /dev/null +++ b/src/NHibernate.Test.VisualBasic/Issues/GH3716/Entity.vb @@ -0,0 +1,7 @@ +Namespace Issues.GH3716 + Public Class Entity + Public Overridable Property Id As Guid + + Public Overridable Property Date1 As Date? + End Class +End Namespace diff --git a/src/NHibernate.Test.VisualBasic/Issues/GH3716/Fixture.vb b/src/NHibernate.Test.VisualBasic/Issues/GH3716/Fixture.vb new file mode 100644 index 00000000000..cff78cfc770 --- /dev/null +++ b/src/NHibernate.Test.VisualBasic/Issues/GH3716/Fixture.vb @@ -0,0 +1,58 @@ +Imports NHibernate.Linq +Imports NUnit.Framework + +Namespace Issues.GH3716 + + Public Class Fixture + Inherits IssueTestCase + + Protected Overrides Sub OnSetUp() + + Using session As ISession = OpenSession() + + Using transaction As ITransaction = session.BeginTransaction() + + Dim e1 = New Entity + e1.Date1 = New Date(2017, 12, 3) + session.Save(e1) + + Dim e2 = New Entity + e2.Date1 = New Date(2017, 12, 1) + session.Save(e2) + + Dim e3 = New Entity + session.Save(e3) + + session.Flush() + transaction.Commit() + + End Using + + End Using + End Sub + + Protected Overrides Sub OnTearDown() + + Using session As ISession = OpenSession() + + Using transaction As ITransaction = session.BeginTransaction() + + session.Delete("from System.Object") + + session.Flush() + transaction.Commit() + + End Using + + End Using + End Sub + + + Public Sub ShouldBeAbleToUpdateWithAnonymousType() + + Using session As ISession = OpenSession() + session.Query(Of Entity).Update(Function(x) New With {.Date1 = Date.Today}) + End Using + End Sub + End Class +End Namespace diff --git a/src/NHibernate.Test.VisualBasic/Issues/GH3716/Issues.GH3716.Mappings.hbm.xml b/src/NHibernate.Test.VisualBasic/Issues/GH3716/Issues.GH3716.Mappings.hbm.xml new file mode 100644 index 00000000000..5ce0f339870 --- /dev/null +++ b/src/NHibernate.Test.VisualBasic/Issues/GH3716/Issues.GH3716.Mappings.hbm.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/NHibernate.Test.VisualBasic/NHibernate.Test.VisualBasic.vbproj b/src/NHibernate.Test.VisualBasic/NHibernate.Test.VisualBasic.vbproj index 5ea684f06b2..ff258df5705 100644 --- a/src/NHibernate.Test.VisualBasic/NHibernate.Test.VisualBasic.vbproj +++ b/src/NHibernate.Test.VisualBasic/NHibernate.Test.VisualBasic.vbproj @@ -26,7 +26,6 @@ - diff --git a/src/NHibernate/Linq/DmlExpressionRewriter.cs b/src/NHibernate/Linq/DmlExpressionRewriter.cs index 782318a64a7..57415affbc4 100644 --- a/src/NHibernate/Linq/DmlExpressionRewriter.cs +++ b/src/NHibernate/Linq/DmlExpressionRewriter.cs @@ -25,10 +25,10 @@ void AddSettersFromBindings(IEnumerable bindings, string path) switch (node.BindingType) { case MemberBindingType.Assignment: - AddSettersFromAssignment((MemberAssignment)node, subPath); + AddSettersFromAssignment((MemberAssignment) node, subPath); break; case MemberBindingType.MemberBinding: - AddSettersFromBindings(((MemberMemberBinding)node).Bindings, subPath); + AddSettersFromBindings(((MemberMemberBinding) node).Bindings, subPath); break; default: throw new InvalidOperationException($"{node.BindingType} is not supported"); @@ -53,10 +53,10 @@ void AddSettersFromAnonymousConstructor(NewExpression newExpression, string path switch (argument.NodeType) { case ExpressionType.New: - AddSettersFromAnonymousConstructor((NewExpression)argument, subPath); + AddSettersFromAnonymousConstructor((NewExpression) argument, subPath); break; case ExpressionType.MemberInit: - AddSettersFromBindings(((MemberInitExpression)argument).Bindings, subPath); + AddSettersFromBindings(((MemberInitExpression) argument).Bindings, subPath); break; default: _assignments.Add(subPath.Substring(1), Expression.Lambda(argument, _parameters)); @@ -121,8 +121,8 @@ public static Expression PrepareExpressionFromAnonymous(Expression sour if (expression == null) throw new ArgumentNullException(nameof(expression)); - // Anonymous initializations are not implemented as member initialization but as plain constructor call. - var newExpression = expression.Body as NewExpression ?? + // Anonymous initializations are not implemented as member initialization but as plain constructor call, potentially wrapped in a Convert expression + var newExpression = UnwrapConvertExpression(expression.Body) as NewExpression ?? throw new ArgumentException("The expression must be an anonymous initialization, e.g. x => new { Name = x.Name, Age = x.Age + 5 }"); var instance = new DmlExpressionRewriter(expression.Parameters); @@ -130,6 +130,16 @@ public static Expression PrepareExpressionFromAnonymous(Expression sour return PrepareExpression(sourceExpression, instance._assignments); } + private static Expression UnwrapConvertExpression(Expression expression) + { + if (expression is UnaryExpression ue && ue.NodeType == ExpressionType.Convert) + { + return ue.Operand; + } + + return expression; + } + public static Expression PrepareExpression(Expression sourceExpression, IReadOnlyDictionary assignments) { var lambda = ConvertAssignmentsToBlockExpression(assignments);