Skip to content

Commit 428fb5d

Browse files
committed
Convert enum values to workaround Npgsql > 4.0 strict type checking. Fixes #105
1 parent 1a76a29 commit 428fb5d

3 files changed

Lines changed: 139 additions & 0 deletions

File tree

src/EntityFramework6.Npgsql/NpgsqlServices.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
using Npgsql.SqlGenerators;
3333
using DbConnection = System.Data.Common.DbConnection;
3434
using DbCommand = System.Data.Common.DbCommand;
35+
using System.Data.Common;
3536

3637
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
3738

@@ -73,6 +74,26 @@ internal DbCommand CreateDbCommand(Version serverVersion, DbCommandTree commandT
7374
return command;
7475
}
7576

77+
protected override void SetDbParameterValue(DbParameter parameter, TypeUsage parameterType, object value)
78+
{
79+
base.SetDbParameterValue(parameter, parameterType, value);
80+
ConvertValueToNumericIfEnum(parameter);
81+
}
82+
83+
// Npgsql > 4.0 does strict type checks on integral values and fails with enums passed with numeric DbType.
84+
static void ConvertValueToNumericIfEnum(DbParameter parameter)
85+
{
86+
var parameterValueObjectType = parameter.Value.GetType();
87+
88+
if (!parameterValueObjectType.IsEnum)
89+
{
90+
return;
91+
}
92+
93+
var underlyingType = Enum.GetUnderlyingType(parameterValueObjectType);
94+
parameter.Value = Convert.ChangeType(parameter.Value, underlyingType);
95+
}
96+
7697
internal void TranslateCommandTree(Version serverVersion, DbCommandTree commandTree, DbCommand command, bool createParametersForNonSelect = true)
7798
{
7899
SqlBaseGenerator sqlGenerator;

test/EntityFramework6.Npgsql.Tests/EntityFrameworkBasicTests.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,5 +847,70 @@ public void Test_string_multiple_null_propagation()
847847
query.ToString());
848848
}
849849
}
850+
851+
[Test]
852+
public void Test_enum()
853+
{
854+
using (var context = new BloggingContext(ConnectionString))
855+
{
856+
context.Database.Log = Console.Out.WriteLine;
857+
858+
context.ClrEnumEntities.Add(
859+
new ClrEnumEntity
860+
{
861+
TestByte = TestByteEnum.Bar,
862+
TestShort = TestShortEnum.Bar,
863+
TestInt = TestIntEnum.Bar,
864+
TestLong = TestLongEnum.Bar
865+
});
866+
context.SaveChanges();
867+
868+
var query = context.ClrEnumEntities.Where(
869+
x => x.TestByte == TestByteEnum.Bar
870+
&& x.TestShort == TestShortEnum.Bar
871+
&& x.TestInt == TestIntEnum.Bar
872+
&& x.TestLong == TestLongEnum.Bar);
873+
874+
var result = query.First();
875+
Assert.That(result.TestByte, Is.EqualTo(TestByteEnum.Bar));
876+
Assert.That(result.TestShort, Is.EqualTo(TestShortEnum.Bar));
877+
Assert.That(result.TestInt, Is.EqualTo(TestIntEnum.Bar));
878+
Assert.That(result.TestLong, Is.EqualTo(TestLongEnum.Bar));
879+
}
880+
}
881+
882+
[Test]
883+
public void Test_enum_composite_key()
884+
{
885+
using (var context = new BloggingContext(ConnectionString))
886+
{
887+
context.Database.Log = Console.Out.WriteLine;
888+
889+
context.ClrEnumCompositeKeyEntities.Add(
890+
new ClrEnumCompositeKeyEntity
891+
{
892+
TestByte = TestByteEnum.Bar,
893+
TestShort = TestShortEnum.Bar,
894+
TestInt = TestIntEnum.Bar,
895+
TestLong = TestLongEnum.Bar
896+
});
897+
context.SaveChanges();
898+
}
899+
900+
using (var context = new BloggingContext(ConnectionString))
901+
{
902+
var result = context.ClrEnumCompositeKeyEntities.Find(
903+
TestByteEnum.Bar,
904+
TestShortEnum.Bar,
905+
TestIntEnum.Bar,
906+
TestLongEnum.Bar);
907+
908+
Assert.That(result, Is.Not.Null);
909+
Assert.That(result.TestByte, Is.EqualTo(TestByteEnum.Bar));
910+
Assert.That(result.TestShort, Is.EqualTo(TestShortEnum.Bar));
911+
Assert.That(result.TestInt, Is.EqualTo(TestIntEnum.Bar));
912+
Assert.That(result.TestLong, Is.EqualTo(TestLongEnum.Bar));
913+
}
914+
}
850915
}
851916
}

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
using NUnit.Framework;
2626
using System;
2727
using System.Collections.Generic;
28+
using System.ComponentModel.DataAnnotations;
2829
using System.Data.Common;
2930
using System.Data.Entity;
3031
using System.Linq;
@@ -102,6 +103,54 @@ public class Post
102103
public virtual Blog Blog { get; set; }
103104
}
104105

106+
public class ClrEnumEntity
107+
{
108+
public int Id { get; set; }
109+
public TestByteEnum TestByte { get; set; }
110+
public TestShortEnum TestShort { get; set; }
111+
public TestIntEnum TestInt { get; set; }
112+
public TestLongEnum TestLong { get; set; }
113+
}
114+
115+
public class ClrEnumCompositeKeyEntity
116+
{
117+
[Key, Column(Order = 1)]
118+
public TestByteEnum TestByte { get; set; }
119+
120+
[Key, Column(Order = 2)]
121+
public TestShortEnum TestShort { get; set; }
122+
123+
[Key, Column(Order = 3)]
124+
public TestIntEnum TestInt { get; set; }
125+
126+
[Key, Column(Order = 4)]
127+
public TestLongEnum TestLong { get; set; }
128+
}
129+
130+
public enum TestByteEnum : byte
131+
{
132+
Foo = 0,
133+
Bar = 1
134+
}
135+
136+
public enum TestShortEnum : short
137+
{
138+
Foo = 0,
139+
Bar = 1
140+
}
141+
142+
public enum TestIntEnum
143+
{
144+
Foo = 0,
145+
Bar = 1
146+
}
147+
148+
public enum TestLongEnum : long
149+
{
150+
Foo = 0,
151+
Bar = 1
152+
}
153+
105154
public class NoColumnsEntity
106155
{
107156
public int Id { get; set; }
@@ -131,6 +180,8 @@ public BloggingContext(string connection)
131180
public DbSet<Blog> Blogs { get; set; }
132181
public DbSet<Post> Posts { get; set; }
133182
public DbSet<NoColumnsEntity> NoColumnsEntities { get; set; }
183+
public DbSet<ClrEnumEntity> ClrEnumEntities { get; set; }
184+
public DbSet<ClrEnumCompositeKeyEntity> ClrEnumCompositeKeyEntities { get; set; }
134185
public DbSet<User> Users { get; set; }
135186
public DbSet<Editor> Editors { get; set; }
136187
public DbSet<Administrator> Administrators { get; set; }
@@ -164,6 +215,8 @@ private static DbCompiledModel CreateModel(NpgsqlConnection connection)
164215
dbModelBuilder.Entity<Blog>();
165216
dbModelBuilder.Entity<Post>();
166217
dbModelBuilder.Entity<NoColumnsEntity>();
218+
dbModelBuilder.Entity<ClrEnumEntity>();
219+
dbModelBuilder.Entity<ClrEnumCompositeKeyEntity>();
167220
dbModelBuilder.Entity<User>();
168221
dbModelBuilder.Entity<Editor>();
169222
dbModelBuilder.Entity<Administrator>();

0 commit comments

Comments
 (0)