Skip to content

Commit 6d2314e

Browse files
committed
Merge branch 'hotfix/3.1.1'
2 parents 51649e9 + c55bef5 commit 6d2314e

10 files changed

+145
-22
lines changed

src/CommonAssemblyInfo.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
[assembly: NeutralResourcesLanguage("en", UltimateResourceFallbackLocation.MainAssembly)]
1717

1818
// The following version attributes get rewritten by GitVersion as part of the build
19-
[assembly: AssemblyVersion("3.1.0")]
20-
[assembly: AssemblyFileVersion("3.1.0")]
21-
[assembly: AssemblyInformationalVersion("3.1.0")]
19+
[assembly: AssemblyVersion("3.1.1")]
20+
[assembly: AssemblyFileVersion("3.1.1")]
21+
[assembly: AssemblyInformationalVersion("3.1.1")]

src/EntityFramework5.Npgsql/EntityFramework5.Npgsql.nuspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
44
<id>EntityFramework5.Npgsql</id>
55
<title>Npgsql for Entity Framework 5</title>
6-
<version>3.1.0</version>
6+
<version>3.1.1</version>
77
<authors>Shay Rojansky, Emil Lenngren, Francisco Figueiredo Jr., Kenji Uno, Jon Asher, John Cooley, Federico Di Gregorio, Jon Hanna, Chris Morgan, Dave Page, Glen Parker, Brar Piening, Hiroshi Saito</authors>
88
<owners>Shay Rojansky, Emil Lenngren, Francisco Figueiredo Jr., Kenji Uno</owners>
99
<licenseUrl>https://github.com/npgsql/EntityFramework6.Npgsql/blob/dev/LICENSE.txt</licenseUrl>

src/EntityFramework6.Npgsql/EntityFramework6.Npgsql.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
<Compile Include="NpgsqlServices.cs" />
7070
<Compile Include="NpgsqlProviderManifest.cs" />
7171
<Compile Include="NpgsqlTextFunctions.cs" />
72+
<Compile Include="NpgsqlTypeFunctions.cs" />
7273
<Compile Include="NpgsqlWeightLabel.cs" />
7374
<Compile Include="Properties\AssemblyInfo.cs" />
7475
<Compile Include="Spatial\PostgisDataReader.cs" />

src/EntityFramework6.Npgsql/EntityFramework6.Npgsql.nuspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
44
<id>EntityFramework6.Npgsql</id>
55
<title>Npgsql for Entity Framework 6</title>
6-
<version>3.1.0</version>
6+
<version>3.1.1</version>
77
<authors>Shay Rojansky, Emil Lenngren, Francisco Figueiredo Jr., Kenji Uno, Jon Asher, John Cooley, Federico Di Gregorio, Jon Hanna, Chris Morgan, Dave Page, Glen Parker, Brar Piening, Hiroshi Saito</authors>
88
<owners>Shay Rojansky, Emil Lenngren, Francisco Figueiredo Jr., Kenji Uno</owners>
99
<licenseUrl>https://github.com/npgsql/EntityFramework6.Npgsql/blob/dev/LICENSE.txt</licenseUrl>

src/EntityFramework6.Npgsql/NpgsqlProviderManifest.cs

+8-13
Original file line numberDiff line numberDiff line change
@@ -371,20 +371,15 @@ public override bool SupportsInExpression()
371371
}
372372

373373
public override ReadOnlyCollection<EdmFunction> GetStoreFunctions()
374-
{
375-
var functions = new List<EdmFunction>();
376-
377-
functions.AddRange(
378-
typeof(NpgsqlTextFunctions).GetTypeInfo()
379-
.GetMethods(BindingFlags.Public | BindingFlags.Static)
380-
.Select(x => new { Method = x, DbFunction = x.GetCustomAttribute<DbFunctionAttribute>() })
381-
.Where(x => x.DbFunction != null)
382-
.Select(x => CreateFullTextEdmFunction(x.Method, x.DbFunction)));
383-
384-
return functions.AsReadOnly();
385-
}
374+
=> new[] { typeof(NpgsqlTextFunctions).GetTypeInfo(), typeof(NpgsqlTypeFunctions) }
375+
.SelectMany(x => x.GetMethods(BindingFlags.Public | BindingFlags.Static))
376+
.Select(x => new { Method = x, DbFunction = x.GetCustomAttribute<DbFunctionAttribute>() })
377+
.Where(x => x.DbFunction != null)
378+
.Select(x => CreateComposableEdmFunction(x.Method, x.DbFunction))
379+
.ToList()
380+
.AsReadOnly();
386381

387-
private static EdmFunction CreateFullTextEdmFunction(MethodInfo method, DbFunctionAttribute dbFunctionInfo)
382+
static EdmFunction CreateComposableEdmFunction(MethodInfo method, DbFunctionAttribute dbFunctionInfo)
388383
{
389384
if (method == null) throw new ArgumentNullException("method");
390385
if (dbFunctionInfo == null) throw new ArgumentNullException("dbFunctionInfo");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Data.Entity;
3+
4+
namespace Npgsql
5+
{
6+
/// <summary>
7+
/// Use this class in LINQ queries to emit type manipulation SQL fragments.
8+
/// </summary>
9+
public static class NpgsqlTypeFunctions
10+
{
11+
/// <summary>
12+
/// Emits an explicit cast for unknown types sent as strings to their correct postgresql type.
13+
/// </summary>
14+
[DbFunction("Npgsql", "cast")]
15+
public static string Cast(string unknownTypeValue, string postgresTypeName)
16+
{
17+
throw new NotSupportedException();
18+
}
19+
}
20+
}

src/EntityFramework6.Npgsql/SqlGenerators/SqlBaseGenerator.cs

+21-3
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,18 @@ private PendingProjectsNode VisitInputWithBinding(DbExpression expression, strin
333333
input.Projection = new CommaSeparatedExpression();
334334

335335
DbNewInstanceExpression projection = (DbNewInstanceExpression)exp.Projection;
336-
RowType rowType = projection.ResultType.EdmType as RowType;
336+
RowType rowType = (RowType)projection.ResultType.EdmType;
337337
for (int i = 0; i < rowType.Properties.Count && i < projection.Arguments.Count; ++i)
338338
{
339-
EdmProperty prop = rowType.Properties[i];
340-
input.Projection.Arguments.Add(new ColumnExpression(projection.Arguments[i].Accept(this), prop.Name, prop.TypeUsage));
339+
var prop = rowType.Properties[i];
340+
var argument = projection.Arguments[i].Accept(this);
341+
var constantArgument = projection.Arguments[i] as DbConstantExpression;
342+
if (constantArgument != null && constantArgument.Value is string)
343+
{
344+
argument = new CastExpression(argument, "varchar");
345+
}
346+
347+
input.Projection.Arguments.Add(new ColumnExpression(argument, prop.Name, prop.TypeUsage));
341348
}
342349

343350
if (enterScope) LeaveExpression(child);
@@ -1210,6 +1217,17 @@ private VisitedExpression VisitFunction(EdmFunction function, IList<DbExpression
12101217

12111218
return new CastExpression(args[0].Accept(this), "tsquery");
12121219
}
1220+
else if (functionName == "cast")
1221+
{
1222+
if (args.Count != 2)
1223+
throw new ArgumentException("Invalid number of arguments. Expected 2.", "args");
1224+
1225+
var typeNameExpression = args[1] as DbConstantExpression;
1226+
if (typeNameExpression == null)
1227+
throw new NotSupportedException("cast type name argument must be a constant expression.");
1228+
1229+
return new CastExpression(args[0].Accept(this), typeNameExpression.Value.ToString());
1230+
}
12131231
}
12141232

12151233
var customFuncCall = new FunctionExpression(

teamcity_set_version.cmd

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
echo ##teamcity[buildNumber '3.1.0-%1']
1+
echo ##teamcity[buildNumber '3.1.1-%1']

test/EntityFramework6.Npgsql.Tests/EntityFrameworkBasicTests.cs

+69
Original file line numberDiff line numberDiff line change
@@ -650,5 +650,74 @@ public void TestScalarValuedStoredFunctions_with_null_StoreFunctionName()
650650
Assert.That(echo, Is.EqualTo(1337));
651651
}
652652
}
653+
654+
[Test]
655+
public void TestCastFunction()
656+
{
657+
using (var context = new BloggingContext(ConnectionString))
658+
{
659+
context.Database.Log = Console.Out.WriteLine;
660+
661+
var varbitVal = "10011";
662+
663+
var blog = new Blog
664+
{
665+
Name = "_",
666+
Posts = new List<Post>
667+
{
668+
new Post
669+
{
670+
Content = "Some post content",
671+
Rating = 1,
672+
Title = "Some post Title",
673+
VarbitColumn = varbitVal
674+
}
675+
}
676+
};
677+
context.Blogs.Add(blog);
678+
context.SaveChanges();
679+
680+
Assert.IsTrue(
681+
context.Posts.Select(
682+
p => NpgsqlTypeFunctions.Cast(p.VarbitColumn, "varbit") == varbitVal).First());
683+
684+
Assert.IsTrue(
685+
context.Posts.Select(
686+
p => NpgsqlTypeFunctions.Cast(p.VarbitColumn, "varbit") == "10011").First());
687+
}
688+
}
689+
690+
[Test]
691+
public void Test_issue_27_select_ef_generated_literals_from_inner_select()
692+
{
693+
using (var context = new BloggingContext(ConnectionString))
694+
{
695+
context.Database.Log = Console.Out.WriteLine;
696+
697+
var blog = new Blog { Name = "Hello" };
698+
context.Users.Add(new Administrator { Blogs = new List<Blog> { blog } });
699+
context.Users.Add(new Editor());
700+
context.SaveChanges();
701+
702+
var administrator = context.Users
703+
.Where(x => x is Administrator) // Removing this changes the query to using a UNION which doesn't fail.
704+
.Select(
705+
x => new
706+
{
707+
// causes entity framework to emit a literal discriminator
708+
Computed = x is Administrator
709+
? "I administrate"
710+
: x is Editor
711+
? "I edit"
712+
: "Unknown",
713+
// causes an inner select to be emitted thus showing the issue
714+
HasBlog = x.Blogs.Any()
715+
})
716+
.First();
717+
718+
Assert.That(administrator.Computed, Is.EqualTo("I administrate"));
719+
Assert.That(administrator.HasBlog, Is.True);
720+
}
721+
}
653722
}
654723
}

test/EntityFramework6.Npgsql.Tests/Support/EntityFrameworkTestBase.cs

+20
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ public class NoColumnsEntity
104104
public int Id { get; set; }
105105
}
106106

107+
[Table("Users")]
108+
public abstract class User
109+
{
110+
public int Id { get; set; }
111+
112+
public IList<Blog> Blogs { get; set; }
113+
}
114+
115+
[Table("Editors")]
116+
public class Editor : User { }
117+
118+
[Table("Administrators")]
119+
public class Administrator : User { }
120+
107121
public class BloggingContext : DbContext
108122
{
109123
public BloggingContext(string connection)
@@ -114,6 +128,9 @@ public BloggingContext(string connection)
114128
public DbSet<Blog> Blogs { get; set; }
115129
public DbSet<Post> Posts { get; set; }
116130
public DbSet<NoColumnsEntity> NoColumnsEntities { get; set; }
131+
public DbSet<User> Users { get; set; }
132+
public DbSet<Editor> Editors { get; set; }
133+
public DbSet<Administrator> Administrators { get; set; }
117134

118135
[DbFunction("BloggingContext", "ClrStoredAddFunction")]
119136
public static int StoredAddFunction(int val1, int val2)
@@ -135,6 +152,9 @@ private static DbCompiledModel CreateModel(NpgsqlConnection connection)
135152
dbModelBuilder.Entity<Blog>();
136153
dbModelBuilder.Entity<Post>();
137154
dbModelBuilder.Entity<NoColumnsEntity>();
155+
dbModelBuilder.Entity<User>();
156+
dbModelBuilder.Entity<Editor>();
157+
dbModelBuilder.Entity<Administrator>();
138158

139159
// Import function
140160
var dbModel = dbModelBuilder.Build(connection);

0 commit comments

Comments
 (0)