Skip to content

Commit 59fb884

Browse files
authored
Fix conversion from a non-nullable value type to the nullable value type (#189)
* #188 * Add tests * 1.0.8.12
1 parent b4b480f commit 59fb884

File tree

6 files changed

+91
-8
lines changed

6 files changed

+91
-8
lines changed

ChangeLog.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
https://github.com/GitTools/GitReleaseNotes
22

3-
GitReleaseNotes.exe . /OutputFile CHANGELOG.md /Version 1.0.8.11
3+
GitReleaseNotes.exe . /OutputFile CHANGELOG.md /Version 1.0.8.12
44

55
GitReleaseNotes.exe . /OutputFile CHANGELOG.md /allTags

src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<Description>Dynamic Linq extensions for EntityFramework which adds Async support</Description>
44
<AssemblyTitle>EntityFramework.DynamicLinq</AssemblyTitle>
5-
<VersionPrefix>1.0.8.11</VersionPrefix>
5+
<VersionPrefix>1.0.8.12</VersionPrefix>
66
<Authors>Stef Heyenrath</Authors>
77
<TargetFrameworks>net45;net46</TargetFrameworks>
88
<DefineConstants>EF</DefineConstants>

src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
<PropertyGroup>
33
<Description>Dynamic Linq extensions for Microsoft.EntityFrameworkCore which adds Async support</Description>
44
<AssemblyTitle>Microsoft.EntityFrameworkCore.DynamicLinq</AssemblyTitle>
5-
<VersionPrefix>1.0.8.11</VersionPrefix>
5+
<VersionPrefix>1.0.8.12</VersionPrefix>
66
<Authors>Stef Heyenrath</Authors>
7-
<TargetFrameworks>net451;net46;netstandard1.3;netstandard2.0;uap10.0</TargetFrameworks>
7+
<TargetFrameworks>net451;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
88
<DefineConstants>$(DefineConstants);EFCORE</DefineConstants>
99
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1010
<AssemblyName>Microsoft.EntityFrameworkCore.DynamicLinq</AssemblyName>

src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs

+19-2
Original file line numberDiff line numberDiff line change
@@ -1246,13 +1246,30 @@ private Expression CreateNewExpression(List<DynamicProperty> properties, List<Ex
12461246
ConstructorInfo ctor = type.GetConstructor(propertyTypes);
12471247
if (ctor != null && ctor.GetParameters().Length == expressions.Count)
12481248
{
1249-
return Expression.New(ctor, expressions, (IEnumerable<MemberInfo>)propertyInfos);
1249+
var expressionsPromoted = new List<Expression>();
1250+
1251+
// Loop all expressions and promote if needed
1252+
for (int i = 0; i < propertyTypes.Length; i++)
1253+
{
1254+
Type propertyType = propertyTypes[i];
1255+
Type expressionType = expressions[i].Type;
1256+
1257+
// Promote from Type to Nullable Type if needed
1258+
expressionsPromoted.Add(ExpressionPromoter.Promote(expressions[i], propertyType, true, true));
1259+
}
1260+
1261+
return Expression.New(ctor, expressionsPromoted, (IEnumerable<MemberInfo>)propertyInfos);
12501262
}
12511263

12521264
MemberBinding[] bindings = new MemberBinding[properties.Count];
12531265
for (int i = 0; i < bindings.Length; i++)
12541266
{
1255-
bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
1267+
PropertyInfo property = type.GetProperty(properties[i].Name);
1268+
Type propertyType = property.PropertyType;
1269+
Type expressionType = expressions[i].Type;
1270+
1271+
// Promote from Type to Nullable Type if needed
1272+
bindings[i] = Expression.Bind(property, ExpressionPromoter.Promote(expressions[i], propertyType, true, true));
12561273
}
12571274

12581275
return Expression.MemberInit(Expression.New(type), bindings);

src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
<PropertyGroup>
33
<Description>This is a .NETStandard/ .NET Core port of the the Microsoft assembly for the .Net 4.0 Dynamic language functionality.</Description>
44
<AssemblyTitle>System.Linq.Dynamic.Core</AssemblyTitle>
5-
<VersionPrefix>1.0.8.11</VersionPrefix>
5+
<VersionPrefix>1.0.8.12</VersionPrefix>
66
<Authors>Microsoft;Scott Guthrie;King Wilder;Nathan Arnott;Stef Heyenrath</Authors>
7-
<TargetFrameworks>net35;net40;net45;net46;uap10.0;netstandard1.3;netstandard2.0</TargetFrameworks>
7+
<TargetFrameworks>net35;net40;net45;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
88
<GenerateDocumentationFile>true</GenerateDocumentationFile>
99
<AssemblyName>System.Linq.Dynamic.Core</AssemblyName>
1010
<AssemblyOriginatorKeyFile>System.Linq.Dynamic.Core.snk</AssemblyOriginatorKeyFile>

test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs

+66
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Linq.PropertyTranslator.Core;
66
using QueryInterceptor.Core;
77
using Xunit;
8+
using NFluent;
89
#if EFCORE
910
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
1011
#else
@@ -161,6 +162,71 @@ public void Select_Dynamic_IntoType()
161162
Assert.Equal(testList.Select(x => x.Profile).Cast<object>().ToList(), userProfiles.ToDynamicList());
162163
}
163164

165+
public class Example
166+
{
167+
public DateTime Time { get; set; }
168+
public DayOfWeek? DOWNull { get; set; }
169+
public DayOfWeek DOW { get; set; }
170+
public int Sec { get; set; }
171+
public int? SecNull { get; set; }
172+
}
173+
174+
public class ExampleWithConstructor
175+
{
176+
public DateTime Time { get; set; }
177+
public DayOfWeek? DOWNull { get; set; }
178+
public DayOfWeek DOW { get; set; }
179+
public int Sec { get; set; }
180+
public int? SecNull { get; set; }
181+
182+
public ExampleWithConstructor(DateTime t, DayOfWeek? dn, DayOfWeek d, int s, int? sn)
183+
{
184+
Time = t;
185+
DOWNull = dn;
186+
DOW = d;
187+
Sec = s;
188+
SecNull = sn;
189+
}
190+
}
191+
192+
[Fact]
193+
public void Select_Dynamic_IntoTypeWithNullableProperties1()
194+
{
195+
// Arrange
196+
var dates = Enumerable.Repeat(0, 7)
197+
.Select((d, i) => new DateTime(2000, 1, 1).AddDays(i).AddSeconds(i))
198+
.AsQueryable();
199+
200+
// Act
201+
IQueryable<Example> result = dates
202+
.Select(d => new Example { Time = d, DOWNull = d.DayOfWeek, DOW = d.DayOfWeek, Sec = d.Second, SecNull = d.Second });
203+
IQueryable<Example> resultDynamic = dates
204+
.Select<Example>("new (it as Time, DayOfWeek as DOWNull, DayOfWeek as DOW, Second as Sec, int?(Second) as SecNull)");
205+
206+
// Assert
207+
Check.That(resultDynamic.First()).Equals(result.First());
208+
Check.That(resultDynamic.Last()).Equals(result.Last());
209+
}
210+
211+
[Fact]
212+
public void Select_Dynamic_IntoTypeWithNullableProperties2()
213+
{
214+
// Arrange
215+
var dates = Enumerable.Repeat(0, 7)
216+
.Select((d, i) => new DateTime(2000, 1, 1).AddDays(i).AddSeconds(i))
217+
.AsQueryable();
218+
219+
// Act
220+
IQueryable<ExampleWithConstructor> result = dates
221+
.Select(d => new ExampleWithConstructor(d, d.DayOfWeek, d.DayOfWeek, d.Second, d.Second));
222+
IQueryable<ExampleWithConstructor> resultDynamic = dates
223+
.Select<ExampleWithConstructor>("new (it as Time, DayOfWeek as DOWNull, DayOfWeek as DOW, Second as Sec, int?(Second) as SecNull)");
224+
225+
// Assert
226+
Check.That(resultDynamic.First()).Equals(result.First());
227+
Check.That(resultDynamic.Last()).Equals(result.Last());
228+
}
229+
164230
[Fact]
165231
public void Select_Dynamic_Exceptions()
166232
{

0 commit comments

Comments
 (0)