Still investigating into ways to interact with composite types in the postgresql database, we defined a composite that uses a database defined enum. While following this outline we added ModelBuilder.ForNpgsqlHasEnum invocations and further added a plugin that translates composite type members such that the composite type member is mapped in the query. It does so by implementing a custom Expression that basically does this:
// a class that extends Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.IMemberTranslatorpublicExpressionTranslate(MemberExpressionmemberExpression){if(memberExpression.Member==ValueMember){returnnewGetCompositeTypeMemberExpression(NpgsqlNameTranslator,memberExpression.Expression,memberExpression.Member);}if(memberExpression.Member==UnitMember){returnnewGetCompositeTypeMemberExpression(NpgsqlNameTranslator,memberExpression.Expression,memberExpression.Member);}returnnull;}// a class that extends System.Linq.Expressions.ExpressionprotectedoverrideExpressionAccept(ExpressionVisitorvisitor){varleftBracket=newCustomUnaryExpression(Instance,"(",Instance.Type,false);varrightBracket=newCustomUnaryExpression(leftBracket,")",Instance.Type,true);varmemberExpression=newCustomUnaryExpression(rightBracket,$".{MemberName}",Type,true);returnmemberExpression;}This works exceptionally well and generates good queries that look alike:
2018-08-14 16:01:27.065 +02:00 [Error] [7856816] [14] [] [] [:] [Microsoft.EntityFrameworkCore.Database.Command] Failed executing DbCommand ("11"ms) [Parameters=[""], CommandType='Text', CommandTimeout='600']"
""SELECT t.id, (t.weight).value, (t.weight).unit
FROM sandbox.weighing AS t"
Unfortunately when adding a simple where clause in the query as follows:
storage.WeighingRecords.Where(t =>t.Weight.Unit==WeightUnit.Tonne)
the following happens:
2018-08-14 16:01:27.065 +02:00 [Error] [7856816] [14] [] [] [:] [Microsoft.EntityFrameworkCore.Database.Command] Failed executing DbCommand ("11"ms) [Parameters=[""], CommandType='Text', CommandTimeout='600']"
""SELECT t.id, (t.weight).value, (t.weight).unit
FROM sandbox.weighing AS t
WHERE (t.weight).unit = 6"
Npgsql.PostgresException (0x80004005): 42883: operator does not exist: units.weight_unit = integer
When I refactor the where argument out of the query such that it becomes a query parameter the query works as expected:
varweightUnit=WeightUnit.Tonne;varactualWeighingRecords=storage.WeighingRecords.Where(t =>t.Weight.Unit==weightUnit)
2018-08-14 16:13:28.360 +02:00 [Information] [8553120] [17] [] [] [:] [Microsoft.EntityFrameworkCore.Database.Command] Executed DbCommand ("10"ms) [Parameters=["@__weightUnit_0='Tonne' (DbType = Object)"], CommandType='Text', CommandTimeout='600']"
""SELECT t.id, (t.weight).value, (t.weight).unit
FROM sandbox.weighing AS t
WHERE (t.weight).unit = @__weightUnit_0"
Is there a way to make this query work without that extra parameter?
Still investigating into ways to interact with composite types in the postgresql database, we defined a composite that uses a database defined enum. While following this outline we added
ModelBuilder.ForNpgsqlHasEnuminvocations and further added a plugin that translates composite type members such that the composite type member is mapped in the query. It does so by implementing a customExpressionthat basically does this:This works exceptionally well and generates good queries that look alike:
Unfortunately when adding a simple where clause in the query as follows:
the following happens:
When I refactor the where argument out of the query such that it becomes a query parameter the query works as expected:
Is there a way to make this query work without that extra parameter?